@powerhousedao/reactor-api 6.2.3-dev.30 → 6.2.3-dev.31

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/graphql/analytics-subgraph.ts","../src/graphql/auth/schema.graphql","../src/graphql/auth/resolvers.ts","../src/graphql/auth/subgraph.ts","../src/graphql/gateway/auth-middleware.ts","../src/graphql/gateway/factory.ts","../src/graphql/gateway/types.ts","../src/http/namespace.ts","../src/http/node-response.ts","../src/http/route-service.ts","../src/http/webhook-verify.ts","../src/http/webhook-service.ts","../src/http/webhook-store.ts","../src/utils/create-schema.ts","../src/graphql/reactor/gen/graphql.ts","../src/graphql/reactor/adapters.ts","../src/graphql/reactor/constants.ts","../src/graphql/reactor/resolvers.ts","../src/graphql/document-model-subgraph.ts","../src/graphql/gateway/drive-middleware.ts","../src/graphql/gateway/drive-ownership-cache.ts","../src/graphql/sse.ts","../src/graphql/graphql-manager.ts","../src/graphql/packages/resolvers.ts","../src/graphql/packages/schema.graphql","../src/graphql/packages/subgraph.ts","../src/graphql/playground.ts","../src/graphql/reactor/requester.ts","../src/graphql/reactor/validation.ts","../src/graphql/reactor/requester.with-zod.ts","../src/graphql/reactor/factory.ts","../src/graphql/reactor/schema.graphql","../src/graphql/reactor/pubsub.ts","../src/graphql/reactor/subgraph.ts","../src/graphql/system/env/getters.ts","../src/graphql/system/env/index.ts","../src/graphql/system/version.ts","../src/graphql/system/subgraph.ts","../src/packages/http-loader.ts","../src/packages/import-loader.ts","../src/packages/package-manager.ts","../src/config.ts","../src/attachment-backend.ts","../src/services/attachment-access.service.ts","../src/graphql/gateway/require-auth-middleware.ts","../src/migrations/001_create_document_permissions.ts","../src/migrations/002_add_document_protection.ts","../src/migrations/003_remove_group_tables.ts","../src/migrations/index.ts","../src/services/auth.service.ts","../src/services/renown-credential-verifier.ts","../src/services/document-permission.service.ts","../src/services/get-parent-ids.ts","../src/services/mcp-request-authorizer.ts","../src/services/sync-serving-gate.ts","../src/services/renown-config.ts","../src/utils/db.ts","../src/server.ts","../src/services/package-storage.ts","../src/services/package-management.service.ts"],"sourcesContent":["import type { GraphQLResolverMap } from \"@apollo/subgraph\";\nimport type { IAnalyticsStore } from \"@powerhousedao/analytics-engine-core\";\nimport { AnalyticsQueryEngine } from \"@powerhousedao/analytics-engine-core\";\nimport {\n AnalyticsModel,\n AnalyticsResolvers,\n typedefs,\n} from \"@powerhousedao/analytics-engine-graphql\";\nimport type { Context, SubgraphArgs } from \"@powerhousedao/reactor-api\";\nimport { gql } from \"graphql-tag\";\nimport { BaseSubgraph } from \"./base-subgraph.js\";\nimport { AuthenticationRequiredError, ForbiddenError } from \"./errors.js\";\n\ntype AnalyticsResolver = (\n parent: unknown,\n args: unknown,\n ctx: Context,\n) => unknown;\n\nconst analyticsResolvers = AnalyticsResolvers as {\n Query: { analytics: AnalyticsResolver };\n} & Record<string, Record<string, AnalyticsResolver>>;\n\nexport class AnalyticsSubgraph extends BaseSubgraph {\n analyticsStore: IAnalyticsStore;\n analyticsModel: AnalyticsModel;\n\n name = \"analytics\";\n typeDefs = gql`\n ${typedefs}\n `;\n\n /**\n * Every analytics field hangs off `Query.analytics`, so gating it gates them\n * all. Series are aggregates a processor built from many documents and carry\n * no document to decide on, so only a caller with policy-wide read (anyone\n * under OPEN, an admin otherwise) may read them.\n */\n resolvers = {\n ...analyticsResolvers,\n Query: {\n ...analyticsResolvers.Query,\n analytics: (parent: unknown, args: unknown, ctx: Context) => {\n this.#assertCanReadAnalytics(ctx);\n return analyticsResolvers.Query.analytics(parent, args, ctx);\n },\n },\n } as GraphQLResolverMap<Context>;\n\n constructor(args: SubgraphArgs) {\n super(args);\n this.analyticsStore = args.analyticsStore;\n\n this.analyticsModel = new AnalyticsModel(\n new AnalyticsQueryEngine(this.analyticsStore),\n );\n\n args.graphqlManager.setAdditionalContextFields({\n dataSources: {\n db: {\n Analytics: this.analyticsModel,\n },\n },\n });\n }\n\n #assertCanReadAnalytics(ctx: Context): void {\n if (this.authorizationService.isSupremeAdmin(ctx.user?.address)) return;\n if (ctx.user?.address) {\n throw new ForbiddenError(\"to read analytics\");\n }\n throw new AuthenticationRequiredError(\"to read analytics\");\n }\n}\n","\"# 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\"","import { GraphQLError } from \"graphql\";\nimport type {\n CanonicalDocumentId,\n IAuthorizationService,\n} from \"../../services/authorization.service.js\";\nimport type { DocumentPermissionService } from \"../../services/document-permission.service.js\";\nimport type { DocumentPermissionLevel } from \"../../utils/db.js\";\n\n// ============================================\n// Document Permission Resolvers\n// ============================================\n\nexport type DocumentAccessInfo = {\n documentId: string;\n permissions: Array<{\n documentId: string;\n userAddress: string;\n permission: DocumentPermissionLevel;\n grantedBy: string;\n createdAt: Date;\n updatedAt: Date;\n }>;\n};\n\nexport async function documentAccess(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: { documentId: CanonicalDocumentId },\n userAddress: string | undefined,\n): Promise<DocumentAccessInfo> {\n if (!userAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n userAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to view its permissions\",\n );\n }\n\n const permissions = await service.getDocumentPermissions(args.documentId);\n\n return {\n documentId: args.documentId,\n permissions,\n };\n}\n\nexport async function userDocumentPermissions(\n service: DocumentPermissionService,\n userAddress: string,\n): Promise<\n Array<{\n documentId: string;\n userAddress: string;\n permission: DocumentPermissionLevel;\n grantedBy: string;\n createdAt: Date;\n updatedAt: Date;\n }>\n> {\n return service.getUserDocuments(userAddress);\n}\n\nexport async function grantDocumentPermission(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: {\n documentId: CanonicalDocumentId;\n userAddress: string;\n permission: DocumentPermissionLevel;\n },\n grantedByAddress: string | undefined,\n): Promise<{\n documentId: string;\n userAddress: string;\n permission: DocumentPermissionLevel;\n grantedBy: string;\n createdAt: Date;\n updatedAt: Date;\n}> {\n if (!grantedByAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n grantedByAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to grant permissions\",\n );\n }\n\n return service.grantPermission(\n args.documentId,\n args.userAddress,\n args.permission,\n grantedByAddress,\n );\n}\n\nexport async function revokeDocumentPermission(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: { documentId: CanonicalDocumentId; userAddress: string },\n revokedByAddress: string | undefined,\n): Promise<boolean> {\n if (!revokedByAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n revokedByAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to revoke permissions\",\n );\n }\n\n await service.revokePermission(args.documentId, args.userAddress);\n return true;\n}\n\n// ============================================\n// Operation Permission Resolvers\n// ============================================\n\nexport type OperationUserPermission = {\n documentId: string;\n operationType: string;\n userAddress: string;\n grantedBy: string;\n createdAt: Date;\n};\n\nexport type OperationPermissionsInfo = {\n documentId: string;\n operationType: string;\n userPermissions: OperationUserPermission[];\n};\n\nexport async function operationPermissions(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: { documentId: CanonicalDocumentId; operationType: string },\n userAddress: string | undefined,\n): Promise<OperationPermissionsInfo> {\n if (!userAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n userAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to view its operation permissions\",\n );\n }\n\n const userPermissions = await service.getOperationUserPermissions(\n args.documentId,\n args.operationType,\n );\n\n return {\n documentId: args.documentId,\n operationType: args.operationType,\n userPermissions,\n };\n}\n\nexport async function canExecuteOperation(\n authorizationService: IAuthorizationService,\n args: { documentId: CanonicalDocumentId; operationType: string },\n userAddress: string | undefined,\n): Promise<boolean> {\n return authorizationService.canMutate(\n args.documentId,\n args.operationType,\n userAddress,\n );\n}\n\nexport async function grantOperationPermission(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: {\n documentId: CanonicalDocumentId;\n operationType: string;\n userAddress: string;\n },\n grantedByAddress: string | undefined,\n): Promise<OperationUserPermission> {\n if (!grantedByAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n grantedByAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to grant operation permissions\",\n );\n }\n\n return service.grantOperationPermission(\n args.documentId,\n args.operationType,\n args.userAddress,\n grantedByAddress,\n );\n}\n\nexport async function revokeOperationPermission(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: {\n documentId: CanonicalDocumentId;\n operationType: string;\n userAddress: string;\n },\n revokedByAddress: string | undefined,\n): Promise<boolean> {\n if (!revokedByAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n revokedByAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to revoke operation permissions\",\n );\n }\n\n await service.revokeOperationPermission(\n args.documentId,\n args.operationType,\n args.userAddress,\n );\n return true;\n}\n\n// ============================================\n// Document Protection Resolvers\n// ============================================\n\nexport type DocumentProtectionInfo = {\n documentId: string;\n protected: boolean;\n ownerAddress: string | null;\n};\n\nexport async function documentProtection(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: { documentId: CanonicalDocumentId },\n userAddress: string | undefined,\n): Promise<DocumentProtectionInfo> {\n if (!userAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n userAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to view its protection info\",\n );\n }\n\n return service.getDocumentProtection(args.documentId);\n}\n\nexport async function setDocumentProtection(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: { documentId: CanonicalDocumentId; protected: boolean },\n userAddress: string | undefined,\n): Promise<DocumentProtectionInfo> {\n if (!userAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n userAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to change protection\",\n );\n }\n\n await service.setDocumentProtection(args.documentId, args.protected);\n return service.getDocumentProtection(args.documentId);\n}\n\nexport async function transferDocumentOwnership(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: { documentId: CanonicalDocumentId; newOwnerAddress: string },\n userAddress: string | undefined,\n): Promise<DocumentProtectionInfo> {\n if (!userAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n userAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to transfer ownership\",\n );\n }\n\n // Revoke old owner's explicit ADMIN grant before transferring\n const previousOwner = await service.getDocumentOwner(args.documentId);\n if (previousOwner) {\n await service.revokePermission(args.documentId, previousOwner);\n }\n\n await service.setDocumentOwner(args.documentId, args.newOwnerAddress);\n\n // Grant ADMIN to new owner\n await service.grantPermission(\n args.documentId,\n args.newOwnerAddress,\n \"ADMIN\",\n userAddress,\n );\n\n return service.getDocumentProtection(args.documentId);\n}\n","import { ConsoleLogger } from \"document-model\";\nimport { GraphQLError } from \"graphql\";\nimport { gql } from \"graphql-tag\";\nimport schemaSource from \"./schema.graphql\";\nimport { BaseSubgraph } from \"../base-subgraph.js\";\nimport type { SubgraphArgs } from \"../types.js\";\nimport * as resolvers from \"./resolvers.js\";\n\n/**\n * Auth Subgraph - handles all document permission and authorization operations\n *\n * This subgraph is conditionally registered based on the DOCUMENT_PERMISSIONS_ENABLED\n * feature flag. When enabled, it provides GraphQL operations for:\n * - Document permissions (grant/revoke user access)\n * - Document protection and ownership\n * - Operation-level permissions (fine-grained operation control)\n */\nexport class AuthSubgraph extends BaseSubgraph {\n private logger = new ConsoleLogger([\"AuthSubgraph\"]);\n\n constructor(args: SubgraphArgs) {\n super(args);\n this.logger.verbose(`constructor()`);\n }\n\n name = \"auth\";\n hasSubscriptions = false;\n\n typeDefs = gql(schemaSource);\n\n resolvers = {\n Query: {\n documentAccess: async (\n _parent: unknown,\n args: { documentId: string },\n ctx: { user?: { address: string } },\n ) => {\n this.logger.debug(\"documentAccess(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.documentAccess(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in documentAccess: @error\", error);\n throw error;\n }\n },\n\n userDocumentPermissions: async (\n _parent: unknown,\n _args: unknown,\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"userDocumentPermissions\");\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n if (!ctx.user?.address) {\n return [];\n }\n try {\n return await resolvers.userDocumentPermissions(\n this.documentPermissionService,\n ctx.user.address,\n );\n } catch (error) {\n this.logger.error(\"Error in userDocumentPermissions: @error\", error);\n throw error;\n }\n },\n\n operationPermissions: async (\n _parent: unknown,\n args: { documentId: string; operationType: string },\n ctx: { user?: { address: string } },\n ) => {\n this.logger.debug(\"operationPermissions(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.operationPermissions(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in operationPermissions: @error\", error);\n throw error;\n }\n },\n\n canExecuteOperation: async (\n _parent: unknown,\n args: { documentId: string; operationType: string },\n ctx: { user?: { address: string } },\n ) => {\n this.logger.debug(\"canExecuteOperation(@args)\", args);\n try {\n return await resolvers.canExecuteOperation(\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in canExecuteOperation: @error\", error);\n throw error;\n }\n },\n\n documentProtection: async (\n _parent: unknown,\n args: { documentId: string },\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"documentProtection(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.documentProtection(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in documentProtection: @error\", error);\n throw error;\n }\n },\n },\n\n Mutation: {\n setDocumentProtection: async (\n _parent: unknown,\n args: { documentId: string; protected: boolean },\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"setDocumentProtection(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.setDocumentProtection(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in setDocumentProtection: @error\", error);\n throw error;\n }\n },\n\n transferDocumentOwnership: async (\n _parent: unknown,\n args: { documentId: string; newOwnerAddress: string },\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"transferDocumentOwnership(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.transferDocumentOwnership(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\n \"Error in transferDocumentOwnership: @error\",\n error,\n );\n throw error;\n }\n },\n\n grantDocumentPermission: async (\n _parent: unknown,\n args: { documentId: string; userAddress: string; permission: string },\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"grantDocumentPermission(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n const resolved = await this.withCanonicalDocumentId(args, ctx);\n return await resolvers.grantDocumentPermission(\n this.documentPermissionService,\n this.authorizationService,\n {\n ...resolved,\n permission: resolved.permission as \"READ\" | \"WRITE\" | \"ADMIN\",\n },\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in grantDocumentPermission: @error\", error);\n throw error;\n }\n },\n\n revokeDocumentPermission: async (\n _parent: unknown,\n args: { documentId: string; userAddress: string },\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"revokeDocumentPermission(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.revokeDocumentPermission(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in revokeDocumentPermission: @error\", error);\n throw error;\n }\n },\n\n // Operation Permission Mutations\n grantOperationPermission: async (\n _parent: unknown,\n args: {\n documentId: string;\n operationType: string;\n userAddress: string;\n },\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"grantOperationPermission(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.grantOperationPermission(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in grantOperationPermission: @error\", error);\n throw error;\n }\n },\n\n revokeOperationPermission: async (\n _parent: unknown,\n args: {\n documentId: string;\n operationType: string;\n userAddress: string;\n },\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"revokeOperationPermission(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.revokeOperationPermission(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\n \"Error in revokeOperationPermission: @error\",\n error,\n );\n throw error;\n }\n },\n },\n };\n\n onSetup(): Promise<void> {\n this.logger.debug(\"Setting up AuthSubgraph\");\n return Promise.resolve();\n }\n}\n","import type { AuthContext, AuthService } from \"../../services/auth.service.js\";\nimport type { FetchHandler } from \"./types.js\";\n\nexport type AuthFetchMiddleware = (handler: FetchHandler) => FetchHandler;\n\nconst authContextMap = new WeakMap<globalThis.Request, AuthContext>();\n\n/** Internal — only `graphql-manager.ts` should call this. */\nexport function getAuthContext(\n request: globalThis.Request,\n): AuthContext | undefined {\n return authContextMap.get(request);\n}\n\nexport function createAuthFetchMiddleware(\n authService: AuthService,\n): AuthFetchMiddleware {\n return (next: FetchHandler): FetchHandler =>\n async (request: globalThis.Request): Promise<globalThis.Response> => {\n const result = await authService.authenticateRequest(request);\n if (result instanceof globalThis.Response) return result;\n authContextMap.set(request, result);\n return next(request);\n };\n}\n","import type { ILogger } from \"document-model\";\nimport type { Context } from \"../types.js\";\nimport type { IGatewayAdapter, IHttpAdapter } from \"./types.js\";\n\nexport type GatewayAdapterType = \"apollo\" | \"mercurius\" | \"stitching\";\nexport type HttpAdapterType = \"express\" | \"fastify\";\n\nexport async function createGatewayAdapter(\n type: GatewayAdapterType,\n logger: ILogger,\n): Promise<IGatewayAdapter<Context>> {\n switch (type) {\n case \"apollo\": {\n const { ApolloGatewayAdapter } =\n await import(\"./adapter-gateway-apollo.js\");\n return new ApolloGatewayAdapter(logger);\n }\n case \"mercurius\": {\n const { MercuriusGatewayAdapter } =\n await import(\"./adapter-gateway-mercurius.js\");\n return new MercuriusGatewayAdapter(logger);\n }\n case \"stitching\": {\n const { StitchingGatewayAdapter } =\n await import(\"./adapter-gateway-stitching.js\");\n return new StitchingGatewayAdapter(logger);\n }\n }\n}\n\nexport type HttpAdapterSetup = {\n adapter: IHttpAdapter;\n};\n\nexport async function createHttpAdapter(\n type: HttpAdapterType,\n): Promise<HttpAdapterSetup> {\n switch (type) {\n case \"express\": {\n const { createExpressHttpAdapter } =\n await import(\"./adapter-http-express.js\");\n return createExpressHttpAdapter();\n }\n case \"fastify\": {\n const { createFastifyHttpAdapter } =\n await import(\"./adapter-http-fastify.js\");\n return createFastifyHttpAdapter();\n }\n }\n}\n","import type { CorsOptions } from \"cors\";\nimport type { DocumentNode, GraphQLSchema } from \"graphql\";\nimport type http from \"node:http\";\nimport type { WebSocketServer } from \"ws\";\n\nexport type TlsOptions =\n | { keyPath: string; certPath: string }\n | { cert: Buffer | string; key: Buffer | string }\n | true;\n\n// Framework-agnostic context factory - receives the Fetch API Request for the current operation\nexport type GatewayContextFactory<TContext = unknown> = (\n request: Request,\n) => Promise<TContext>;\n\n// Opaque per-connection key carrying what `onConnect` resolved to `context`.\n\n/** Under graphql-ws this is `ctx.extra`, created once per socket. */\nexport type WsConnection = object;\n\n// Called per operation, so it must be pure: verifying belongs in `onConnect`.\nexport type WsContextFactory<TContext = unknown> = (\n connectionParams: Record<string, unknown>,\n connection: WsConnection,\n) => Promise<TContext>;\n\n// Admits a connection once, at `ConnectionInit`; `false` closes 4403, retryable.\n\n// It must never throw: an escaping exception closes 4500, which is fatal.\nexport type WsConnectHandler = (\n connectionParams: Record<string, unknown>,\n connection: WsConnection,\n) => Promise<boolean>;\n\n// One object, so no adapter can thread `context` without `onConnect`.\nexport type WsHandlers<TContext = unknown> = {\n onConnect: WsConnectHandler;\n context: WsContextFactory<TContext>;\n};\n\n// Why a WebSocket handshake was refused, carried as the reason on a 4403 close.\n\n// A wire contract. A client reads these to tell an auth refusal -- which no\n// number of retries clears, only a credential change -- from a transient close.\n\n// Both stay 4403: graphql-ws keeps that code retryable, and a reconnect\n// re-evaluates `connectionParams`, so a socket refused before a sign-in does\n// succeed after one. 4401 would kill it before a fresh token could be offered.\n\n// Keep the values stable. A close reason caps at 123 UTF-8 bytes.\n\n/** No authenticated caller resolved, and REQUIRE_AUTHENTICATED_CALLER wants one. */\nexport const WS_CLOSE_REASON_AUTHENTICATION_REQUIRED =\n \"authentication-required\";\n\n/** A bearer was sent and could not be verified. */\nexport const WS_CLOSE_REASON_BEARER_REJECTED = \"bearer-rejected\";\n\n/** Every reason a refusal closes with, for a client matching on the set. */\nexport const WS_AUTH_CLOSE_REASONS = [\n WS_CLOSE_REASON_AUTHENTICATION_REQUIRED,\n WS_CLOSE_REASON_BEARER_REJECTED,\n] as const;\n\nexport type WsDisposer = { dispose: () => void | Promise<void> };\n\n// A Fetch API handler - framework agnostic\nexport type FetchHandler = (request: Request) => Promise<Response>;\n\n/**\n * Handle to a route registered directly on the adapter. Packages hot-reload,\n * so every registration is reversible; disposing a route that is already gone\n * is a no-op.\n *\n * The handle *is* the capability to remove that one route: holding it is the\n * only way to take the route back, and it cannot name any other. An opaque\n * integer would let any holder remove any route by arithmetic, and a caller\n * that disposed twice would eventually free somebody else's registration once\n * ids were reused.\n *\n * Distinct from the `ScopedRouteHandle` a package's HTTP scope hands back,\n * which also carries the public URL the route answers on — at this layer there\n * is no namespace to build one from and no knowledge of the host's origin.\n */\nexport interface AdapterRouteHandle {\n dispose(): void;\n}\n\n/**\n * A framework-agnostic description of one subgraph.\n * Used by IGatewayAdapter.createSupergraphHandler() to compose the supergraph:\n * federation adapters treat it as a service to call over HTTP, while the\n * stitching adapter merges its typeDefs and resolvers in-process.\n */\nexport type SubgraphDefinition = {\n name: string;\n typeDefs: DocumentNode;\n url: string;\n /**\n * The subgraph's resolver map, in-process form. Optional: federation\n * adapters (Apollo, Mercurius) execute subgraphs over HTTP and ignore this,\n * while stitching-style adapters merge these resolvers directly into the\n * supergraph schema. Subgraph authors never see this field - it is filled\n * in by the gateway manager from the subgraph's own resolvers.\n */\n resolvers?: Record<string, unknown>;\n};\n\nexport interface IGatewayAdapter<TContext = unknown> {\n /** One-time startup. */\n start(httpServer: http.Server): Promise<void>;\n\n /**\n * Returns a Fetch API handler for the given schema.\n * Caller (IHttpAdapter) is responsible for mounting it at a path.\n */\n createHandler(\n schema: GraphQLSchema,\n contextFactory: GatewayContextFactory<TContext>,\n ): Promise<FetchHandler>;\n\n /**\n * Create a handler that composes all subgraphs into a supergraph (a\n * federation gateway, or a merged in-process schema under the stitching\n * adapter). getSubgraphs is called eagerly (during setup) and again on every\n * updateSupergraph() call.\n */\n createSupergraphHandler(\n getSubgraphs: () => SubgraphDefinition[],\n httpServer: http.Server,\n contextFactory: GatewayContextFactory<TContext>,\n ): Promise<FetchHandler>;\n\n /**\n * Recompose the supergraph from the current subgraph list and push the update\n * to the running gateway (a federation gateway, or a merged in-process schema\n * under the stitching adapter). No-op if createSupergraphHandler() has not\n * been called yet, or after stop().\n */\n updateSupergraph(): Promise<void>;\n\n // Attach WebSocket subscriptions. Both halves of `handlers` must be passed on.\n\n /** Without `onConnect`, refusing would mean throwing: an unretryable 4500. */\n attachWebSocket(\n wsServer: WebSocketServer,\n schema: GraphQLSchema,\n handlers: WsHandlers<TContext>,\n ): WsDisposer;\n\n stop(): Promise<void>;\n}\n\n/**\n * Methods a node route may bind. OPTIONS is excluded: the framework's CORS\n * plugin owns preflight, and a duplicate registration conflicts at startup.\n */\nexport type HttpMethod = \"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\";\n\nexport interface NodeRouteOptions {\n /** Serve sub-paths too, not just an exact path match. */\n prefix?: boolean;\n\n /**\n * Deliver the request body as the client sent it: unparsed and byte-exact.\n * The handler reads `req` itself; the `body` argument stays undefined.\n *\n * Without this, the body has already been parsed by the time the handler\n * runs, so a signature computed over the raw payload cannot be verified —\n * re-encoding loses key order, whitespace and duplicate keys. This is the\n * one capability a webhook endpoint cannot do without, and the reason a\n * route needs to be dispatched ahead of the body parsers rather than behind\n * them.\n */\n rawBody?: boolean;\n}\n\nexport interface IHttpAdapter {\n /** Set up CORS and body-parser equivalent middleware. */\n setupMiddleware(config: {\n corsOptions?: CorsOptions;\n bodyLimit?: string;\n }): void;\n\n /**\n * Mount a Fetch API handler. Returns a handle whose `dispose()` removes it.\n * - exact = false (default): exact path match.\n * - exact = true: prefix match - handler also receives all sub-paths.\n *\n * Mounting a path that already holds a fetch mount of the same kind\n * replaces the previous one (last write wins).\n */\n mount(\n path: string,\n handler: FetchHandler,\n options?: {\n prefix?: boolean;\n /** @deprecated Misleading name: this always meant *prefix*, not exact. */\n exact?: boolean;\n },\n ): AdapterRouteHandle;\n\n /**\n * Register a GET-only route that returns a Fetch Response (for health,\n * explorer, etc.). Returns a handle whose `dispose()` removes it.\n */\n getRoute(\n path: string,\n handler: (request: Request) => Response | Promise<Response>,\n ): AdapterRouteHandle;\n\n /**\n * Start listening on the given port. Returns the underlying http.Server\n * so callers can attach WebSocket servers. Without `host` it binds the\n * wildcard address.\n */\n listen(port: number, tls?: TlsOptions, host?: string): Promise<http.Server>;\n\n /**\n * Mount a raw Connect/Express-compatible middleware function (e.g. Vite dev\n * server middleware). The implementation is adapter-specific; for Express this\n * is equivalent to `app.use(middleware)`.\n */\n mountRawMiddleware(middleware: unknown): void;\n\n /**\n * Register a method-specific route handler using Node.js core HTTP types.\n * Use this when a Fetch API FetchHandler is not possible (e.g. streaming\n * protocols that require direct access to IncomingMessage/ServerResponse).\n *\n * The req/res objects are `http.IncomingMessage`/`http.ServerResponse`\n * (Express Request/Response are compatible subtypes). Returns a handle\n * whose `dispose()` removes it.\n */\n mountNodeRoute(\n method: HttpMethod,\n path: string,\n // Node route handlers may be synchronous or async; the adapter does not\n // await them, and answers a throw or rejection with a 500.\n handler: (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body?: unknown,\n ) => void | Promise<void>,\n options?: NodeRouteOptions,\n ): AdapterRouteHandle;\n\n /**\n * Register framework-specific Sentry error-capturing middleware after all routes\n * are mounted. Each adapter calls the Sentry setup function appropriate for its\n * framework (e.g. setupExpressErrorHandler, setupFastifyErrorHandler).\n * No-op if Sentry is not relevant for the adapter.\n */\n setupSentryErrorHandler(sentry: object): void;\n\n /** The raw framework handle (e.g. Express app). Cast as needed at call sites. */\n readonly handle: unknown;\n}\n","import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/**\n * A package's namespace is its npm name, used verbatim as one or two path\n * segments. Nothing is slugged: dropping the scope, folding `.`/`_` to `-` or\n * lower-casing would all map distinct package names onto one namespace, and a\n * lossy mapping means two packages can silently claim the same URL space.\n * Verbatim is injective, so there is no collision left to detect.\n */\n\n/**\n * npm's package-name grammar, per segment. Deliberately the same shape the HTTP\n * package loader validates with, so a name that can be installed can be routed.\n */\nconst SEGMENT = /^[a-z0-9][-a-z0-9._]*$/i;\n\n/** Segments that would read as path traversal rather than as a name. */\nconst TRAVERSAL = new Set([\".\", \"..\"]);\n\nexport class InvalidNamespaceError extends Error {}\n\n/**\n * Turns a package name into the path segments it occupies.\n * `@powerhousedao/workflow` → [\"@powerhousedao\", \"workflow\"]\n * `document-model` → [\"document-model\"]\n */\nexport function namespaceSegments(packageName: string): string[] {\n if (!packageName) {\n throw new InvalidNamespaceError(\"Package name is empty\");\n }\n\n const scoped = packageName.startsWith(\"@\");\n const parts = (scoped ? packageName.slice(1) : packageName).split(\"/\");\n\n if (parts.length !== (scoped ? 2 : 1)) {\n throw new InvalidNamespaceError(\n `\"${packageName}\" is not a package name: expected ${\n scoped ? \"@scope/name\" : \"name\"\n }`,\n );\n }\n\n for (const part of parts) {\n if (TRAVERSAL.has(part) || !SEGMENT.test(part)) {\n throw new InvalidNamespaceError(\n `\"${packageName}\" contains a segment that is not a valid npm name part: \"${part}\"`,\n );\n }\n }\n\n return scoped ? [`@${parts[0]!}`, parts[1]!] : parts;\n}\n\n/**\n * The path a package's routes hang off, relative to the package prefix.\n * Scoped names occupy two segments — the addressing unpkg and jsdelivr use.\n */\nexport function namespacePath(packageName: string): string {\n return namespaceSegments(packageName).join(\"/\");\n}\n\n/**\n * The same path with the leading `@` percent-encoded. Both routers match the\n * raw pathname, so a client that percent-encodes each segment would otherwise\n * 404. Registering both spellings avoids decoding the pathname before matching,\n * which would turn `%2f` into `/` and let a crafted URL cross segment\n * boundaries. `%40` cannot introduce a boundary, which is what makes this safe.\n */\nexport function encodedNamespacePath(packageName: string): string | undefined {\n const path = namespacePath(packageName);\n return path.startsWith(\"@\") ? `%40${path.slice(1)}` : undefined;\n}\n\n/**\n * A route path a package supplied. Must be relative and must not climb out of\n * the scope.\n */\nexport function assertRelativeRoutePath(path: string): string {\n if (path.startsWith(\"/\")) {\n throw new InvalidNamespaceError(\n `Route path \"${path}\" must be relative to the scope, not absolute`,\n );\n }\n if (/^[a-z][a-z0-9+.-]*:/i.test(path)) {\n throw new InvalidNamespaceError(\n `Route path \"${path}\" must be a path, not a URL`,\n );\n }\n if (path.split(\"/\").some((segment) => TRAVERSAL.has(segment))) {\n throw new InvalidNamespaceError(\n `Route path \"${path}\" must not contain \".\" or \"..\" segments`,\n );\n }\n return path.replace(/^\\/+|\\/+$/g, \"\");\n}\n\n/**\n * Resolves the npm name a package is routed under from the key the package\n * manager holds it by. That key is the specifier as configured, which is not\n * always a name:\n * - `@scope/pkg` — already a name.\n * - `@scope/pkg@1.3.9` — a registry spec; only the loader strips the tag.\n * - `/Users/me/project` — the local project, which switchboard registers by\n * `process.cwd()`. Its real name lives in its package.json.\n *\n * Deriving a URL segment straight from the key would give a developer's home\n * directory a route namespace, so the path form is resolved rather than slugged.\n */\nexport function resolvePackageName(\n key: string,\n readPackageJsonName: (dir: string) => string | undefined = defaultReadName,\n): string {\n const withoutVersion = stripVersionSpec(key);\n if (isPackageName(withoutVersion)) return withoutVersion;\n\n if (key.startsWith(\"/\") || key.startsWith(\".\")) {\n const name = readPackageJsonName(key);\n if (name && isPackageName(name)) return name;\n throw new InvalidNamespaceError(\n `Package at \"${key}\" has no usable name in its package.json, so it cannot host routes`,\n );\n }\n\n throw new InvalidNamespaceError(\n `\"${key}\" is not a package name and not a path, so it cannot host routes`,\n );\n}\n\nfunction isPackageName(value: string): boolean {\n try {\n namespaceSegments(value);\n return true;\n } catch {\n return false;\n }\n}\n\n/** `@scope/pkg@1.3.9` → `@scope/pkg`; `pkg@1.0.0` → `pkg`. */\nfunction stripVersionSpec(key: string): string {\n const at = key.lastIndexOf(\"@\");\n if (at <= 0) return key;\n return key.slice(0, at);\n}\n\nfunction defaultReadName(dir: string): string | undefined {\n try {\n // Deliberately synchronous and best-effort: this runs once per package at\n // load, and a missing or unreadable manifest is a normal outcome.\n const raw = readFileSync(join(dir, \"package.json\"), \"utf8\");\n const parsed = JSON.parse(raw) as { name?: unknown };\n return typeof parsed.name === \"string\" ? parsed.name : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * A mount path the host named for one of its own route groups.\n *\n * The host owns the whole URL space — it holds the adapter — so unlike a\n * package it may name an absolute path. That is the difference between hosting\n * and being hosted, and it is why this lives on the service rather than on a\n * scope: a package is only ever handed a scope, and a scope has no way to\n * express a path outside itself.\n *\n * What the host still may not name is anything that is not one stable literal\n * prefix. A traversal segment, or a pattern segment, would make the group's own\n * routes unpredictable relative to each other. Returns the normalized path,\n * with a leading and no trailing slash.\n */\nexport function assertHostMountPath(path: string): string {\n if (!path.startsWith(\"/\")) {\n throw new InvalidNamespaceError(\n `Host mount path \"${path}\" must be absolute, e.g. \"/webhooks\"`,\n );\n }\n\n const segments = path.split(\"/\").filter((segment) => segment.length > 0);\n if (segments.length === 0) {\n throw new InvalidNamespaceError(\n `Host mount path \"${path}\" is the whole URL space, which is the adapter rather than a scope of it`,\n );\n }\n\n for (const segment of segments) {\n if (TRAVERSAL.has(segment)) {\n throw new InvalidNamespaceError(\n `Host mount path \"${path}\" must not contain \".\" or \"..\" segments`,\n );\n }\n if (segment.startsWith(\":\") || segment.includes(\"*\")) {\n throw new InvalidNamespaceError(\n `Host mount path \"${path}\" must be a literal prefix, not a pattern: \"${segment}\"`,\n );\n }\n }\n\n return `/${segments.join(\"/\")}`;\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport type { RouteTransport } from \"./types.js\";\n\n/** Converts Node incoming headers to Fetch Headers. */\nexport function fetchHeaders(req: IncomingMessage): Headers {\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (value === undefined) continue;\n headers.set(key, Array.isArray(value) ? value.join(\", \") : value);\n }\n return headers;\n}\n\n/**\n * Where the request reached the host. `trustProxy` says whether the\n * `x-forwarded-*` headers may be believed: they are client-written, so with no\n * proxy in front a caller could pick the origin a route advertises. The `host`\n * header is always read, being the request's own target.\n */\nexport function resolveTransport(\n req: IncomingMessage,\n trustProxy = false,\n): RouteTransport {\n const header = (name: string): string | undefined => {\n const value = req.headers[name];\n const first = Array.isArray(value) ? value[0] : value;\n return first?.split(\",\")[0]?.trim() || undefined;\n };\n const forwarded = (name: string): string | undefined =>\n trustProxy ? header(name) : undefined;\n\n const encrypted = (req.socket as { encrypted?: boolean }).encrypted === true;\n const proto =\n forwarded(\"x-forwarded-proto\") ?? (encrypted ? \"https\" : \"http\");\n const host = forwarded(\"x-forwarded-host\") ?? header(\"host\") ?? \"localhost\";\n const prefix = forwarded(\"x-forwarded-prefix\") ?? \"\";\n\n return { proto, host, prefix, baseUrl: `${proto}://${host}${prefix}` };\n}\n\nexport class BodyTooLargeError extends Error {}\n\n/**\n * Buffers the request body, refusing anything past `maxBytes`.\n *\n * Written with events rather than `for await`, because an async iterator\n * destroys the stream when the loop exits early — which tears down the socket\n * before a 413 can be written to it. The stream is left paused instead, so the\n * caller can answer and then close the connection deliberately.\n */\nexport function readBody(\n req: IncomingMessage,\n maxBytes: number,\n): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n let settled = false;\n\n const settle = (error?: Error): void => {\n if (settled) return;\n settled = true;\n req.off(\"data\", onData);\n req.off(\"end\", onEnd);\n req.off(\"error\", onError);\n req.pause();\n if (error) reject(error);\n else resolve(Buffer.concat(chunks));\n };\n\n const onData = (chunk: Buffer): void => {\n size += chunk.length;\n if (size > maxBytes) {\n settle(new BodyTooLargeError(`Body exceeds ${maxBytes} bytes`));\n return;\n }\n chunks.push(chunk);\n };\n const onEnd = (): void => settle();\n const onError = (error: Error): void => settle(error);\n\n req.on(\"data\", onData);\n req.once(\"end\", onEnd);\n req.once(\"error\", onError);\n });\n}\n\n/**\n * Copies a Fetch Response onto a Node response, streaming the body. A HEAD\n * response carries headers only, however the handler filled the body.\n */\nexport async function writeResponse(\n res: ServerResponse,\n response: Response,\n method: string,\n): Promise<void> {\n if (res.writableEnded || res.headersSent) return;\n\n res.statusCode = response.status;\n response.headers.forEach((value, key) => {\n res.setHeader(key, value);\n });\n\n if (!response.body || method.toUpperCase() === \"HEAD\") {\n res.end();\n return;\n }\n\n const source = Readable.fromWeb(response.body as never);\n res.on(\"close\", () => source.destroy());\n await pipeline(source, res);\n}\n\n/** Answers with a JSON error, unless the response is already underway. */\nexport function writeError(\n res: ServerResponse,\n status: number,\n message: string,\n): void {\n if (res.writableEnded || res.headersSent) {\n res.destroy();\n return;\n }\n const body = JSON.stringify({ error: message });\n res.statusCode = status;\n res.setHeader(\"content-type\", \"application/json\");\n res.setHeader(\"content-length\", Buffer.byteLength(body));\n res.end(body);\n}\n","import { childLogger } from \"document-model\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport posix from \"node:path/posix\";\nimport { Readable } from \"node:stream\";\nimport type {\n AdapterRouteHandle as AdapterHandle,\n IHttpAdapter,\n} from \"../graphql/gateway/types.js\";\nimport type { AuthService } from \"../services/auth.service.js\";\nimport type { WebhookService } from \"./webhook-service.js\";\nimport {\n assertHostMountPath,\n assertRelativeRoutePath,\n encodedNamespacePath,\n InvalidNamespaceError,\n namespacePath,\n resolvePackageName,\n} from \"./namespace.js\";\nimport {\n BodyTooLargeError,\n fetchHeaders,\n readBody,\n resolveTransport,\n writeError,\n writeResponse,\n} from \"./node-response.js\";\nimport type {\n IHttpScope,\n IWebhookScope,\n NodeRouteSpec,\n RouteActor,\n RouteAuth,\n RouteContext,\n ScopedRouteHandle,\n RouteHandler,\n RouteMethod,\n RouteOptions,\n RouteSpec,\n} from \"./types.js\";\n\nconst logger = childLogger([\"reactor-api\", \"http-routes\"]);\n\n/** The segment package routes live under, inside the host's base path. */\nexport const PACKAGE_ROUTE_SEGMENT = \"api\";\n\n/** The namespace core's own subgraphs and services register under. */\nexport const CORE_PACKAGE_NAME = \"@powerhousedao/reactor-api\";\n\n/** Generous enough for any request a route should be buffering at all. */\nconst DEFAULT_MAX_BODY_BYTES = 1_048_576;\n\nconst ANONYMOUS: RouteActor = { user: undefined, authEnabled: false };\n\nexport interface HttpRouteServiceOptions {\n httpAdapter: IHttpAdapter;\n /** Absent on a host with no webhook store; `scope.webhooks` then refuses. */\n webhooks?: WebhookService;\n /** The host's base path, i.e. config.basePath. */\n basePath?: string;\n /** Absent when auth is disabled host-wide; every route then sees an anonymous actor. */\n authService?: AuthService;\n /** The host's public origin; empty when unknowable, the only case where advertised URLs degrade to paths. */\n publicUrl?: string;\n /** Whether to believe the `X-Forwarded-*` headers that name the request's public origin.\n * Off by default: they are client-written, so with no proxy in front a caller could choose the origin a route advertises. */\n trustProxy?: boolean;\n}\n\ntype Registration = { path: string; handles: AdapterHandle[] };\n\n/** Owns the URL space packages serve from, handing each a scope bound to its own namespace. The prefix nests inside\n * the host's base path (`<basePath>/api`), so core collisions are prevented by URL shape, not a reserved-name list. */\nexport class HttpRouteService {\n readonly #adapter: IHttpAdapter;\n readonly #authService: AuthService | undefined;\n readonly #prefix: string;\n readonly #publicUrl: string;\n readonly #trustProxy: boolean;\n readonly #scopes = new Map<string, HttpScope>();\n\n readonly #webhooks: WebhookService | undefined;\n\n constructor({\n httpAdapter,\n basePath = \"/\",\n authService,\n webhooks,\n publicUrl = \"\",\n trustProxy = false,\n }: HttpRouteServiceOptions) {\n this.#adapter = httpAdapter;\n this.#authService = authService;\n this.#webhooks = webhooks;\n this.#publicUrl = publicUrl.replace(/\\/+$/, \"\");\n this.#trustProxy = trustProxy;\n this.#prefix = posix.join(\"/\", basePath, PACKAGE_ROUTE_SEGMENT);\n }\n\n /** The absolute path packages are mounted under. */\n get prefix(): string {\n return this.#prefix;\n }\n\n /** The scope for a package; idempotent per name, so a reload cannot accumulate namespaces. Throws when two packages\n * resolve to one namespace — with verbatim names that means one package configured twice, a genuine ambiguity. */\n scopeFor(packageKey: string): IHttpScope {\n const packageName = resolvePackageName(packageKey);\n const namespace = namespacePath(packageName);\n const encoded = encodedNamespacePath(packageName);\n return this.#scope({\n owner: packageName,\n base: posix.join(this.#prefix, namespace),\n encodedBase: encoded ? posix.join(this.#prefix, encoded) : undefined,\n claim: `the route namespace \"${namespace}\"`,\n webhooks: this.#webhooks?.scopeFor(packageName),\n onDispose: () => this.#webhooks?.disposeScope(packageName),\n });\n }\n\n /** A scope at a host-named path; on the service, not `IHttpScope`, so a package can never name one. Namespacing is package\n * policy: the host owns its URL space and third parties hold its URLs, so the path is verbatim and outside the package prefix. */\n hostScope(name: string, mountPath: string): IHttpScope {\n const base = assertHostMountPath(mountPath);\n if (base === this.#prefix || base.startsWith(`${this.#prefix}/`)) {\n throw new InvalidNamespaceError(\n `Host scope \"${name}\" cannot mount at \"${base}\": that is the package route prefix, which packages own`,\n );\n }\n return this.#scope({\n owner: name,\n base,\n encodedBase: undefined,\n claim: `the mount path \"${base}\"`,\n // None of its own: a token-addressed endpoint belongs to whoever minted the token, always a package.\n webhooks: undefined,\n onDispose: () => undefined,\n });\n }\n\n /** Idempotent per base path, so a package reload cannot accumulate namespaces. Two owners wanting one path is an error —\n * with verbatim names that needs one package configured twice at different versions, a genuine ambiguity, not a clash. */\n #scope(options: {\n owner: string;\n base: string;\n encodedBase: string | undefined;\n claim: string;\n webhooks: IWebhookScope | undefined;\n onDispose: () => void;\n }): IHttpScope {\n const { owner, base } = options;\n const existing = this.#scopes.get(base);\n if (existing) {\n if (existing.owner !== owner) {\n throw new Error(\n `\"${owner}\" wants ${options.claim}, which \"${existing.owner}\" already holds`,\n );\n }\n return existing;\n }\n\n const scope = new HttpScope({\n owner,\n base,\n encodedBase: options.encodedBase,\n publicUrl: this.#publicUrl,\n trustProxy: this.#trustProxy,\n adapter: this.#adapter,\n authService: this.#authService,\n webhooks: options.webhooks,\n onDispose: () => {\n this.#scopes.delete(base);\n options.onDispose();\n },\n });\n this.#scopes.set(base, scope);\n return scope;\n }\n\n /** Like {@link scopeFor}, but never throws: a key resolving to no usable npm name gets a scope that refuses\n * registrations, so one unroutable package cannot stop the host booting — it fails only if it serves a route. */\n scopeForOrNull(packageKey: string): IHttpScope {\n try {\n return this.scopeFor(packageKey);\n } catch (error) {\n if (!(error instanceof InvalidNamespaceError)) throw error;\n // Scoped package names carry a leading `@`, which the logger reads as\n // a replacement token: pass them positionally so the name survives.\n logger.warn(\n 'Package \"@package\" cannot host HTTP routes: @reason',\n packageKey,\n error.message,\n );\n return new UnroutableScope(packageKey, error.message);\n }\n }\n\n /** Releases a package's routes, e.g. when it is replaced or removed. */\n disposeScope(packageKey: string): void {\n try {\n const namespace = namespacePath(resolvePackageName(packageKey));\n this.#scopes.get(posix.join(this.#prefix, namespace))?.dispose();\n } catch (error) {\n if (!(error instanceof InvalidNamespaceError)) throw error;\n }\n }\n\n disposeAll(): void {\n for (const scope of [...this.#scopes.values()]) scope.dispose();\n }\n}\n\ninterface HttpScopeOptions {\n /** A package's npm name, or the host's name for one of its route groups. */\n owner: string;\n /** Absolute path every route in the scope hangs off. */\n base: string;\n /** The same base with a scoped name's `@` percent-encoded, when it has one. */\n encodedBase: string | undefined;\n publicUrl: string;\n trustProxy: boolean;\n adapter: IHttpAdapter;\n authService: AuthService | undefined;\n webhooks: IWebhookScope | undefined;\n onDispose: () => void;\n}\n\nclass HttpScope implements IHttpScope {\n readonly owner: string;\n readonly #base: string;\n readonly #publicUrl: string;\n readonly #trustProxy: boolean;\n readonly #encodedBase: string | undefined;\n readonly #adapter: IHttpAdapter;\n readonly #authService: AuthService | undefined;\n readonly #onDispose: () => void;\n readonly #registrations = new Map<string, Registration>();\n readonly #webhooks: IWebhookScope;\n\n constructor(options: HttpScopeOptions) {\n this.owner = options.owner;\n this.#base = options.base;\n this.#publicUrl = options.publicUrl;\n this.#trustProxy = options.trustProxy;\n this.#encodedBase = options.encodedBase;\n this.#adapter = options.adapter;\n this.#authService = options.authService;\n this.#onDispose = options.onDispose;\n this.#webhooks = options.webhooks ?? unavailableWebhooks(options.owner);\n }\n\n get baseUrl(): string {\n return `${this.#publicUrl}${this.#base}`;\n }\n\n get webhooks(): IWebhookScope {\n return this.#webhooks;\n }\n\n get(path: string, a: RouteOptions | RouteHandler, b?: RouteHandler) {\n return this.#shorthand(\"GET\", path, a, b);\n }\n post(path: string, a: RouteOptions | RouteHandler, b?: RouteHandler) {\n return this.#shorthand(\"POST\", path, a, b);\n }\n put(path: string, a: RouteOptions | RouteHandler, b?: RouteHandler) {\n return this.#shorthand(\"PUT\", path, a, b);\n }\n patch(path: string, a: RouteOptions | RouteHandler, b?: RouteHandler) {\n return this.#shorthand(\"PATCH\", path, a, b);\n }\n delete(path: string, a: RouteOptions | RouteHandler, b?: RouteHandler) {\n return this.#shorthand(\"DELETE\", path, a, b);\n }\n head(path: string, a: RouteOptions | RouteHandler, b?: RouteHandler) {\n return this.#shorthand(\"HEAD\", path, a, b);\n }\n\n #shorthand(\n method: RouteMethod,\n path: string,\n a: RouteOptions | RouteHandler,\n b?: RouteHandler,\n ): ScopedRouteHandle {\n const options = typeof a === \"function\" ? {} : a;\n const handler = typeof a === \"function\" ? a : b;\n if (!handler) {\n throw new Error(`Route ${method} ${path} was registered with no handler`);\n }\n return this.route({ ...options, method, path, handler });\n }\n\n route(spec: RouteSpec): ScopedRouteHandle {\n const body = spec.body ?? \"parsed\";\n return this.#register(spec, (req, res, ctx) =>\n this.#serve(spec, body, req, res, ctx),\n );\n }\n\n nodeRoute(spec: NodeRouteSpec): ScopedRouteHandle {\n return this.#register(spec, (req, res, ctx) => spec.handler(req, res, ctx));\n }\n\n dispose(): void {\n for (const registration of this.#registrations.values()) {\n for (const handle of registration.handles) handle.dispose();\n }\n this.#registrations.clear();\n this.#onDispose();\n }\n\n /** Mounts one route under this scope's namespace, in both the verbatim and the\n * percent-encoded spelling of a scoped name. */\n #register(\n spec: {\n method: RouteMethod | RouteMethod[];\n path: string;\n auth?: RouteAuth;\n maxBodyBytes?: number;\n prefix?: boolean;\n },\n run: (\n req: IncomingMessage,\n res: ServerResponse,\n ctx: Omit<RouteContext, \"rawBody\" | \"signal\">,\n ) => void | Promise<void>,\n ): ScopedRouteHandle {\n const relative = assertRelativeRoutePath(spec.path);\n const methods = Array.isArray(spec.method) ? spec.method : [spec.method];\n const routePath = relative ? posix.join(this.#base, relative) : this.#base;\n\n const key = `${methods.join(\",\")} ${routePath}`;\n if (this.#registrations.has(key)) {\n // Silent shadowing is how a route disappears without anyone noticing;\n // for a security-relevant surface that has to be loud.\n throw new Error(`Route ${key} is already registered by \"${this.owner}\"`);\n }\n\n const handles: AdapterHandle[] = [];\n const paths = [routePath];\n if (this.#encodedBase) {\n paths.push(\n relative ? posix.join(this.#encodedBase, relative) : this.#encodedBase,\n );\n }\n\n for (const path of paths) {\n for (const method of methods) {\n handles.push(\n this.#adapter.mountNodeRoute(\n method,\n path,\n (req, res) => {\n void this.#guard(spec, req, res, run);\n },\n // The service owns body handling for every route it registers, so\n // it always takes the unparsed stream from the adapter.\n { rawBody: true, prefix: spec.prefix },\n ),\n );\n }\n }\n\n this.#registrations.set(key, { path: routePath, handles });\n logger.debug(\"Registered @route for @package\", key, this.owner);\n\n return {\n url: `${this.#publicUrl}${routePath}`,\n dispose: () => {\n const registration = this.#registrations.get(key);\n if (!registration) return;\n for (const handle of registration.handles) handle.dispose();\n this.#registrations.delete(key);\n },\n };\n }\n\n /** Authenticate, then run. */\n async #guard(\n spec: { auth?: RouteAuth },\n req: IncomingMessage,\n res: ServerResponse,\n run: (\n req: IncomingMessage,\n res: ServerResponse,\n ctx: Omit<RouteContext, \"rawBody\" | \"signal\">,\n ) => void | Promise<void>,\n ): Promise<void> {\n try {\n const actor = await this.#authenticate(spec.auth ?? \"renown\", req, res);\n if (actor === REJECTED) return;\n\n await run(req, res, {\n params: routeParams(req),\n user: actor?.user,\n authEnabled: actor?.authEnabled ?? false,\n transport: resolveTransport(req, this.#trustProxy),\n });\n } catch (error) {\n logger.error(\n \"Route handler failed for @package\",\n this.owner,\n error as Error,\n );\n writeError(res, 500, \"Internal server error\");\n }\n }\n\n /** Resolves the caller, answering the request itself when the route refuses it;\n * returns REJECTED in that case so the caller stops. */\n async #authenticate(\n auth: RouteAuth,\n req: IncomingMessage,\n res: ServerResponse,\n ): Promise<RouteActor | undefined | typeof REJECTED> {\n if (auth === \"public\") return undefined;\n\n if (typeof auth === \"function\") {\n const result = await auth(req);\n if (!result.authorized) {\n if (\"response\" in result) {\n await writeResponse(res, result.response, req.method ?? \"GET\");\n } else {\n writeError(res, result.status, result.message);\n }\n return REJECTED;\n }\n return undefined;\n }\n\n // No auth service means auth is disabled host-wide: every caller is the\n // anonymous actor, which is the only way to opt out of bearer checking.\n if (!this.#authService) return ANONYMOUS;\n\n const result = await this.#authService.verifyBearer(\n req.headers.authorization,\n );\n\n if (result instanceof Response) {\n await writeResponse(res, result, req.method ?? \"GET\");\n return REJECTED;\n }\n\n if (result.auth_enabled && !result.user && auth === \"renown\") {\n writeError(res, 401, \"Authentication required\");\n return REJECTED;\n }\n\n return { user: result.user, authEnabled: result.auth_enabled };\n }\n\n /** Builds the Fetch Request from the raw stream and runs the handler. */\n async #serve(\n spec: RouteSpec,\n body: NonNullable<RouteSpec[\"body\"]>,\n req: IncomingMessage,\n res: ServerResponse,\n ctx: Omit<RouteContext, \"rawBody\" | \"signal\">,\n ): Promise<void> {\n const method = req.method ?? \"GET\";\n const url = `${ctx.transport.baseUrl}${req.url ?? \"/\"}`;\n\n const controller = new AbortController();\n req.once(\"close\", () => controller.abort());\n\n let raw: Buffer | undefined;\n let init: RequestInit & { duplex?: \"half\" } = {\n method,\n headers: fetchHeaders(req),\n signal: controller.signal,\n };\n\n const carriesBody = method !== \"GET\" && method !== \"HEAD\";\n if (carriesBody && body !== \"none\") {\n if (body === \"stream\") {\n init = {\n ...init,\n body: Readable.toWeb(req) as ReadableStream,\n duplex: \"half\",\n };\n } else {\n try {\n raw = await readBody(\n req,\n spec.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES,\n );\n } catch (error) {\n if (error instanceof BodyTooLargeError) {\n // The rest of the body is never read, so the connection cannot be\n // reused: leftover bytes would be parsed as the next request.\n res.setHeader(\"connection\", \"close\");\n res.once(\"finish\", () => req.destroy());\n writeError(res, 413, \"Payload too large\");\n return;\n }\n throw error;\n }\n // Verbatim bytes, so a handler verifying a signature over the payload sees what the client sent.\n // A view, not a copy: an upload can be large.\n /* The narrowing is for TypeScript: `BufferSource` excludes a SharedArrayBuffer-backed view while Buffer's\n * `.buffer` is the wider `ArrayBufferLike`; Node never pools a Buffer on shared memory, so it is sound. */\n if (raw.length)\n init = {\n ...init,\n body: new Uint8Array(\n raw.buffer as ArrayBuffer,\n raw.byteOffset,\n raw.byteLength,\n ),\n };\n }\n }\n\n const response = await spec.handler(new Request(url, init), {\n ...ctx,\n rawBody: body === \"raw\" ? (raw ?? Buffer.alloc(0)) : undefined,\n signal: controller.signal,\n });\n\n await writeResponse(res, response, method);\n }\n}\n\nconst REJECTED = Symbol(\"rejected\");\n\nfunction routeParams(req: IncomingMessage): Record<string, string> {\n const params = (req as IncomingMessage & { params?: unknown }).params;\n if (!params || typeof params !== \"object\") return {};\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(params)) {\n if (typeof value === \"string\") out[key] = value;\n else if (Array.isArray(value)) out[key] = value.join(\"/\");\n }\n return out;\n}\n\n/** Stands in for a package that cannot be routed — its key resolves to no npm name. Registering a route throws with\n * the reason; nothing else does, so the package still loads and its non-HTTP behaviour is unaffected. */\nclass UnroutableScope implements IHttpScope {\n readonly owner: string;\n readonly baseUrl = \"\";\n readonly #reason: string;\n\n constructor(packageKey: string, reason: string) {\n this.owner = packageKey;\n this.#reason = reason;\n }\n\n #refuse(): never {\n throw new Error(\n `Package \"${this.owner}\" cannot host HTTP routes: ${this.#reason}`,\n );\n }\n\n get(): never {\n this.#refuse();\n }\n post(): never {\n this.#refuse();\n }\n put(): never {\n this.#refuse();\n }\n patch(): never {\n this.#refuse();\n }\n delete(): never {\n this.#refuse();\n }\n head(): never {\n this.#refuse();\n }\n route(): never {\n this.#refuse();\n }\n nodeRoute(): never {\n this.#refuse();\n }\n get webhooks(): IWebhookScope {\n return unavailableWebhooks(this.owner);\n }\n dispose(): void {\n // Nothing was ever registered.\n }\n}\n\n/** Stands in when the host has no webhook store configured. */\nfunction unavailableWebhooks(packageName: string): IWebhookScope {\n return {\n // No endpoints exist to advertise, so the question does not arise.\n hasPublicOrigin: false,\n register: () =>\n Promise.reject(\n new Error(\n `Webhooks are not available on this host, so \"${packageName}\" cannot register one`,\n ),\n ),\n };\n}\n","/** Signature verification for inbound webhooks, over the raw bytes: a parse/re-encode\n * round trip changes key order, whitespace and duplicate keys, so every scheme here needs the exact octets the provider sent. */\nimport { createHmac, timingSafeEqual, type BinaryLike } from \"node:crypto\";\n\nimport type {\n WebhookHashAlgorithm,\n WebhookScheme,\n WebhookSignatureEncoding,\n WebhookVerification,\n} from \"@powerhousedao/shared/processors\";\n\nexport type {\n WebhookHashAlgorithm,\n WebhookScheme,\n WebhookSignatureEncoding,\n WebhookVerification,\n};\n\nexport const DEFAULT_TOLERANCE_SECONDS = 300;\n\n/** Header each scheme reads when the caller does not name one: the name the format is\n * most often carried in, not a property of it, so `WebhookVerification.header` overrides any of them. */\nexport const DEFAULT_SCHEME_HEADER: Record<WebhookScheme, string> = {\n none: \"\",\n token: \"x-webhook-token\",\n hmac: \"x-signature\",\n \"hmac-prefixed\": \"x-hub-signature-256\",\n \"hmac-timestamped\": \"stripe-signature\",\n};\n\nexport type VerifyResult = { ok: true } | { ok: false; reason: string };\n\nconst OK: VerifyResult = { ok: true };\n\n/** Constant-time over equal-length inputs; a length mismatch is already a rejection, so\n * the early return leaks nothing a caller could not measure. */\nfunction secureEquals(a: string, b: string): boolean {\n const left = Buffer.from(a, \"utf8\");\n const right = Buffer.from(b, \"utf8\");\n if (left.length !== right.length) return false;\n return timingSafeEqual(left, right);\n}\n\nfunction hmacDigest(\n secret: string,\n payload: BinaryLike,\n verification: WebhookVerification,\n): string {\n return createHmac(verification.algorithm ?? \"sha256\", secret)\n .update(payload)\n .digest(verification.encoding ?? \"hex\");\n}\n\n/** Hex folds case, so an uppercased digest still verifies. Base64 must not: two distinct\n * digests can differ only in case, so folding there would accept a signature that is not the one computed. */\nfunction digestEquals(\n presented: string,\n expected: string,\n verification: WebhookVerification,\n): boolean {\n const candidate = presented.trim();\n if ((verification.encoding ?? \"hex\") === \"base64\") {\n return secureEquals(candidate, expected);\n }\n return secureEquals(candidate.toLowerCase(), expected.toLowerCase());\n}\n\n/** The label `hmac-prefixed` expects before the digest. */\nfunction signaturePrefix(verification: WebhookVerification): string {\n return verification.prefix ?? `${verification.algorithm ?? \"sha256\"}=`;\n}\n\n/** `t=<unix>,v1=<hex>[,v1=<hex>…]`. Several `v1` values appear while a secret is being\n * rotated, and any one of them matching is a pass. */\nfunction parseTimestampedHeader(value: string): {\n timestamp?: number;\n signatures: string[];\n} {\n const signatures: string[] = [];\n let timestamp: number | undefined;\n for (const part of value.split(\",\")) {\n const separator = part.indexOf(\"=\");\n if (separator < 0) continue;\n const key = part.slice(0, separator).trim();\n const item = part.slice(separator + 1).trim();\n if (key === \"t\") timestamp = Number(item);\n // Not lower-cased here: the encoding decides whether case matters, and\n // digestEquals is where that is known.\n else if (key === \"v1\") signatures.push(item);\n }\n return { timestamp, signatures };\n}\n\nexport function schemeHeader(verification: WebhookVerification): string {\n return (\n verification.header ?? DEFAULT_SCHEME_HEADER[verification.scheme]\n ).toLowerCase();\n}\n\n/** Verifies a delivery against the configured scheme; `raw` must be the exact bytes\n * received. The reason is for the log only: callers answer a fixed 401, so a probing sender learns nothing from the body. */\nexport function verifyWebhook(options: {\n verification: WebhookVerification;\n headers: Record<string, string>;\n raw: Buffer;\n now?: Date;\n}): VerifyResult {\n const { verification, headers, raw } = options;\n if (verification.scheme === \"none\") return OK;\n if (!verification.secret) {\n return { ok: false, reason: \"signing secret missing\" };\n }\n\n const header = schemeHeader(verification);\n // Absent and empty are one case: the index type hides the former.\n const presented: string | undefined = headers[header];\n if (!presented) return { ok: false, reason: `header \"${header}\" absent` };\n\n const secret = verification.secret;\n const tolerance = verification.toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;\n\n switch (verification.scheme) {\n case \"token\":\n return secureEquals(presented, secret)\n ? OK\n : { ok: false, reason: \"token mismatch\" };\n case \"hmac\":\n return digestEquals(\n presented,\n hmacDigest(secret, raw, verification),\n verification,\n )\n ? OK\n : { ok: false, reason: \"hmac mismatch\" };\n case \"hmac-prefixed\": {\n const expected = `${signaturePrefix(verification)}${hmacDigest(secret, raw, verification)}`;\n return digestEquals(presented, expected, verification)\n ? OK\n : { ok: false, reason: \"hmac mismatch\" };\n }\n case \"hmac-timestamped\": {\n const { timestamp, signatures } = parseTimestampedHeader(presented);\n if (timestamp === undefined || !Number.isFinite(timestamp)) {\n return { ok: false, reason: \"no timestamp in the signature header\" };\n }\n if (signatures.length === 0) {\n return { ok: false, reason: \"no v1 signature in the header\" };\n }\n const nowMs = (options.now ?? new Date()).getTime();\n if (Math.abs(nowMs / 1000 - timestamp) > tolerance) {\n return { ok: false, reason: \"timestamp outside the replay window\" };\n }\n const expected = hmacDigest(\n secret,\n Buffer.concat([Buffer.from(`${timestamp}.`, \"utf8\"), raw]),\n verification,\n );\n // Every candidate is compared, so rotation does not change the timing.\n let matched = false;\n for (const signature of signatures) {\n if (digestEquals(signature, expected, verification)) matched = true;\n }\n return matched ? OK : { ok: false, reason: \"hmac mismatch\" };\n }\n }\n}\n\n/** Headers that would put a credential in a log or run journal. The configured signature\n * header joins them: it is an HMAC of the body under a live secret. */\nconst REDACTED_HEADERS = new Set([\n \"authorization\",\n \"proxy-authorization\",\n \"cookie\",\n \"set-cookie\",\n \"x-api-key\",\n \"x-webhook-token\",\n \"x-signature\",\n \"x-hub-signature\",\n \"x-hub-signature-256\",\n \"stripe-signature\",\n]);\n\nexport const REDACTED = \"[redacted]\";\n\nexport function redactHeaders(\n headers: Record<string, string>,\n extra?: string,\n): Record<string, string> {\n const redacted: Record<string, string> = {};\n for (const [name, value] of Object.entries(headers)) {\n const key = name.toLowerCase();\n redacted[key] =\n REDACTED_HEADERS.has(key) || (extra && key === extra.toLowerCase())\n ? REDACTED\n : value;\n }\n return redacted;\n}\n\n/** JSON and form bodies become objects; anything else stays decoded text, so a verified\n * XML or CSV payload is still reachable downstream. */\nexport function parseWebhookBody(raw: Buffer, contentType?: string): unknown {\n if (raw.length === 0) return undefined;\n const type = (contentType ?? \"\").split(\";\")[0]!.trim().toLowerCase();\n const text = raw.toString(\"utf8\");\n if (type === \"application/json\" || type.endsWith(\"+json\")) {\n try {\n return JSON.parse(text) as unknown;\n } catch {\n // A malformed body is still evidence; hand the text through.\n return text;\n }\n }\n if (type === \"application/x-www-form-urlencoded\") {\n return Object.fromEntries(new URLSearchParams(text));\n }\n return text;\n}\n","import { childLogger } from \"document-model\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport posix from \"node:path/posix\";\nimport { BodyTooLargeError, readBody, writeError } from \"./node-response.js\";\nimport type {\n IHttpScope,\n IWebhookScope,\n ScopedRouteHandle,\n WebhookPolicy,\n WebhookField,\n WebhookSpec,\n} from \"./types.js\";\nimport type { IWebhookStore } from \"./webhook-store.js\";\nimport {\n parseWebhookBody,\n redactHeaders,\n schemeHeader,\n verifyWebhook,\n} from \"./webhook-verify.js\";\n\nconst logger = childLogger([\"reactor-api\", \"webhooks\"]);\n\n/** The flat, token-addressed path family. */\nexport const WEBHOOK_SEGMENT = \"webhooks\";\n\nconst DEFAULT_MAX_BODY_BYTES = 1_048_576;\nconst DEFAULT_DEDUPE_TTL_SECONDS = 300;\n\nexport interface WebhookServiceOptions {\n store: IWebhookStore;\n basePath?: string;\n /** Public origin to advertise, e.g. https://switchboard.example. */\n publicUrl?: string;\n}\n\ntype Registration = { namespace: string; spec: WebhookSpec };\n\n/** One host route for `/webhooks/:token`, dispatching by token. The flat path leaks\n * neither package nor document; the namespace lives in the token record, which is also what stops one package's token reaching another's handler. */\nexport class WebhookService {\n readonly #store: IWebhookStore;\n readonly #path: string;\n readonly #publicUrl: string | undefined;\n // Layer 1, not the adapter: same dispatch, refusal and disposal path every package\n // route gets, so the two cannot drift on what a request means.\n #scope: IHttpScope | undefined;\n readonly #registrations = new Map<string, Registration>();\n #routes: ScopedRouteHandle[] = [];\n\n constructor({ store, basePath = \"/\", publicUrl }: WebhookServiceOptions) {\n this.#store = store;\n this.#path = posix.join(\"/\", basePath, WEBHOOK_SEGMENT);\n this.#publicUrl = publicUrl?.replace(/\\/+$/, \"\");\n }\n\n /** The scope the endpoint family serves from, handed over once the route service exists;\n * separate from the constructor only because that service takes this one as an option. */\n attach(scope: IHttpScope): void {\n this.#scope = scope;\n }\n\n async init(): Promise<void> {\n await this.#store.init();\n if (this.#routes.length) return;\n if (!this.#scope) {\n throw new Error(\n \"The webhook service has no HTTP scope; the host must call attach() before a package registers\",\n );\n }\n\n // Every method: a provider's verification round may probe with GET even when its\n // deliveries are POST, and refusing a method is the registration's call.\n\n // Truthfully public: the token in the path is the whole credential, and verification\n // is the registration's policy, not the host's auth — as is the rate, applied per registration in `#deliver`.\n this.#routes = [\n this.#scope.nodeRoute({\n method: [\"DELETE\", \"GET\", \"HEAD\", \"PATCH\", \"POST\", \"PUT\"],\n path: \":token\",\n auth: \"public\",\n handler: (req, res, ctx) => void this.#deliver(req, res, ctx.params),\n }),\n ];\n }\n\n dispose(): void {\n for (const handle of this.#routes) handle.dispose();\n this.#routes = [];\n this.#registrations.clear();\n }\n\n /** The facade a package's HTTP scope exposes as `scope.webhooks`. */\n scopeFor(namespace: string): IWebhookScope {\n return {\n hasPublicOrigin: this.hasPublicOrigin,\n register: async (spec: WebhookSpec) => {\n await this.init();\n const key = `${namespace}|${spec.name}`;\n this.#registrations.set(key, { namespace, spec });\n return {\n endpointFor: async (ownerKey: string) => {\n const row = await this.#store.ensure(\n namespace,\n spec.name,\n ownerKey,\n );\n return {\n token: row.token,\n url: this.urlFor(row.token),\n createdAt: row.createdAt,\n };\n },\n revoke: (ownerKey: string) =>\n this.#store.revoke(namespace, spec.name, ownerKey),\n list: async () =>\n (await this.#store.list(namespace, spec.name)).map((row) => ({\n key: row.ownerKey,\n token: row.token,\n url: this.urlFor(row.token),\n createdAt: row.createdAt,\n })),\n };\n },\n };\n }\n\n /** Releases every registration a package made. */\n disposeScope(namespace: string): void {\n for (const [key, registration] of this.#registrations) {\n if (registration.namespace === namespace) {\n this.#registrations.delete(key);\n }\n }\n }\n\n /** The URL to hand a provider. Absolute whenever the host knows its own origin: a\n * relative path is useless to the third party that has to call it. */\n urlFor(token: string): string {\n const path = posix.join(this.#path, token);\n return this.#publicUrl ? `${this.#publicUrl}${path}` : path;\n }\n\n /** Whether `urlFor` can produce something a provider could call. */\n get hasPublicOrigin(): boolean {\n return this.#publicUrl !== undefined;\n }\n\n async #deliver(\n req: IncomingMessage,\n res: ServerResponse,\n params: Record<string, string>,\n ): Promise<void> {\n const token = params.token;\n if (!token) {\n writeError(res, 404, \"Unknown endpoint\");\n return;\n }\n\n try {\n const row = await this.#store.find(token);\n // Unknown, malformed and disarmed all answer this same 404, so a prober cannot tell\n // a live endpoint from a dead one; a live endpoint's verification failure answers 401, the caller having proved the token exists by holding it.\n if (!row) {\n writeError(res, 404, \"Unknown endpoint\");\n return;\n }\n\n const registrationKey = `${row.namespace}|${row.endpoint}`;\n const registration = this.#registrations.get(registrationKey);\n if (!registration) {\n // The token is real but its package is not loaded on this host.\n writeError(res, 503, \"Endpoint temporarily unavailable\");\n return;\n }\n\n const { spec } = registration;\n const method = (req.method ?? \"POST\").toUpperCase();\n\n const perEndpoint = spec.policyFor\n ? await spec.policyFor(row.ownerKey)\n : {};\n if (!perEndpoint) {\n // Not armed. Answers as an unknown token does, deliberately.\n writeError(res, 404, \"Unknown endpoint\");\n return;\n }\n\n // Declared defaults, then what this endpoint carries. Only `defaults` participates,\n // which is why the spec keeps its policy fields under their own key.\n const policy: WebhookPolicy = { ...spec.defaults, ...perEndpoint };\n\n if (policy.methods && !policy.methods.includes(method)) {\n writeError(res, 405, \"Method not allowed\");\n return;\n }\n\n let raw: Buffer;\n try {\n raw = await readBody(\n req,\n policy.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES,\n );\n } catch (error) {\n if (error instanceof BodyTooLargeError) {\n res.setHeader(\"connection\", \"close\");\n res.once(\"finish\", () => req.destroy());\n writeError(res, 413, \"Payload too large\");\n return;\n }\n throw error;\n }\n\n const verification = policy.verify;\n if (verification) {\n const result = verifyWebhook({\n verification,\n headers: headerRecord(req),\n raw,\n });\n if (!result.ok) {\n // The namespace starts with `@`, the logger's replacement token; passed\n // positionally it stays a value, not a placeholder to be substituted away.\n logger.warn(\n \"Rejected webhook delivery for @package/@endpoint: @reason\",\n row.namespace,\n row.endpoint,\n result.reason,\n );\n writeError(res, 401, \"Signature verification failed\");\n return;\n }\n }\n\n // A fixed base: only the query is read from this, so the request's own\n // origin never enters it and cannot be spoofed through it.\n const url = new URL(req.url ?? \"/\", \"http://localhost\");\n const queryParams = Object.fromEntries(url.searchParams);\n const signatureHeader = verification\n ? schemeHeader(verification)\n : undefined;\n const headers = headerRecord(req);\n const body = parseWebhookBody(raw, headers[\"content-type\"]);\n\n // The provider's verification round: echo the value, invoke nothing. From the merged\n // policy, not the registration — the echoed field is per-endpoint configuration.\n const challenge = challengeValue(\n policy.challengeField,\n queryParams,\n headers,\n body,\n );\n if (challenge !== undefined) {\n res.statusCode = 200;\n res.setHeader(\"content-type\", \"text/plain\");\n res.end(challenge);\n return;\n }\n\n if (policy.dedupe) {\n const key = dedupeKey(policy.dedupe.field, queryParams, headers, body);\n if (\n key !== undefined &&\n (await this.#store.seen(\n token,\n key,\n policy.dedupe.ttlSeconds ?? DEFAULT_DEDUPE_TTL_SECONDS,\n ))\n ) {\n // A redelivery is not an error: answer as though it succeeded, so the\n // provider stops retrying, but run nothing twice.\n res.statusCode = 200;\n res.end();\n return;\n }\n }\n\n const reply = await spec.onRequest({\n key: row.ownerKey,\n method,\n path: url.pathname,\n queryParams,\n headers: redactHeaders(headers, signatureHeader),\n raw,\n body,\n });\n\n res.statusCode = reply.status;\n if (reply.body !== undefined && method !== \"HEAD\") {\n res.setHeader(\"content-type\", reply.contentType ?? \"text/plain\");\n res.end(reply.body);\n } else {\n res.end();\n }\n } catch (error) {\n // Not the token or the URL: the token is the capability, and the URL carries it.\n logger.error(\n \"Webhook delivery failed for @method\",\n req.method,\n error as Error,\n );\n writeError(res, 500, \"Internal server error\");\n }\n }\n}\n\nfunction headerRecord(req: IncomingMessage): Record<string, string> {\n const headers: Record<string, string> = {};\n for (const [name, value] of Object.entries(req.headers)) {\n if (value === undefined) continue;\n headers[name.toLowerCase()] = Array.isArray(value)\n ? value.join(\", \")\n : value;\n }\n return headers;\n}\n\nfunction scalar(value: unknown): string | undefined {\n if (typeof value === \"string\" && value !== \"\") return value;\n if (typeof value === \"number\") return String(value);\n return undefined;\n}\n\n/** Walks a dot-separated path into the parsed body. */\nfunction bodyPath(path: string, body: unknown): string | undefined {\n let current: unknown = body;\n for (const segment of path.split(\".\")) {\n if (!current || typeof current !== \"object\") return undefined;\n current = (current as Record<string, unknown>)[segment];\n }\n return scalar(current);\n}\n\n/** Resolves where a provider put a value. A bare string means query first, then a\n * top-level body field; `{ header }` and `{ body }` reach what that cannot — GitHub's delivery id is a header, Stripe's event id is nested. */\nfunction fieldValue(\n field: WebhookField,\n queryParams: Record<string, string>,\n headers: Record<string, string>,\n body: unknown,\n): string | undefined {\n if (typeof field === \"object\") {\n return \"header\" in field\n ? scalar(headers[field.header.toLowerCase()])\n : bodyPath(field.body, body);\n }\n const fromQuery = scalar(queryParams[field]);\n if (fromQuery !== undefined) return fromQuery;\n return body && typeof body === \"object\"\n ? scalar((body as Record<string, unknown>)[field])\n : undefined;\n}\n\nfunction challengeValue(\n field: WebhookField | undefined,\n queryParams: Record<string, string>,\n headers: Record<string, string>,\n body: unknown,\n): string | undefined {\n return field === undefined\n ? undefined\n : fieldValue(field, queryParams, headers, body);\n}\n\nfunction dedupeKey(\n field: WebhookField,\n queryParams: Record<string, string>,\n headers: Record<string, string>,\n body: unknown,\n): string | undefined {\n return fieldValue(field, queryParams, headers, body);\n}\n","import type { IRelationalDb } from \"@powerhousedao/shared/processors\";\nimport { randomBytes } from \"node:crypto\";\n\n/**\n * Where webhook tokens live. Core-owned and relational rather than per-host, so\n * any host in a fleet can serve any endpoint: a provider's registered URL keeps\n * working after a restart, a redeploy or a request landing on another replica.\n */\nexport interface WebhookEndpointRow {\n token: string;\n /** The owning package's npm name. */\n namespace: string;\n /** The registration within that package. */\n endpoint: string;\n /** The caller's own key, e.g. a document id. Never appears in the URL. */\n ownerKey: string;\n createdAt: string;\n}\n\nexport interface IWebhookStore {\n init(): Promise<void>;\n /** Returns the existing token for this key, or mints one. */\n ensure(\n namespace: string,\n endpoint: string,\n ownerKey: string,\n ): Promise<WebhookEndpointRow>;\n find(token: string): Promise<WebhookEndpointRow | undefined>;\n list(namespace: string, endpoint?: string): Promise<WebhookEndpointRow[]>;\n revoke(namespace: string, endpoint: string, ownerKey: string): Promise<void>;\n /** True when this delivery has been seen before, within the TTL. */\n seen(token: string, key: string, ttlSeconds: number): Promise<boolean>;\n}\n\nconst TOKEN_BYTES = 16;\nexport const TOKEN_PATTERN = /^[0-9a-f]{32}$/;\n\n/** Opaque and unguessable: the URL is a bearer capability held by a third party. */\nexport function newWebhookToken(): string {\n return randomBytes(TOKEN_BYTES).toString(\"hex\");\n}\n\nconst NAMESPACE = \"reactor_webhooks\";\n\ntype Schema = {\n webhook_endpoints: {\n token: string;\n namespace: string;\n endpoint: string;\n owner_key: string;\n created_at: string;\n };\n webhook_deliveries: {\n token: string;\n dedupe_key: string;\n seen_at: string;\n /** Who won the insert; see the comment in seen(). */\n claim_id: string;\n };\n};\n\n/** Relational implementation, over the reactor's own database. */\nexport class RelationalWebhookStore implements IWebhookStore {\n #db: IRelationalDb<Schema> | undefined;\n\n constructor(private readonly relationalDb: IRelationalDb) {}\n\n async init(): Promise<void> {\n if (this.#db) return;\n const db = await this.relationalDb.createNamespace<Schema>(NAMESPACE);\n\n await db.schema\n .createTable(\"webhook_endpoints\")\n .ifNotExists()\n .addColumn(\"token\", \"text\", (col) => col.primaryKey())\n .addColumn(\"namespace\", \"text\", (col) => col.notNull())\n .addColumn(\"endpoint\", \"text\", (col) => col.notNull())\n .addColumn(\"owner_key\", \"text\", (col) => col.notNull())\n .addColumn(\"created_at\", \"text\", (col) => col.notNull())\n .execute();\n\n // One token per (package, registration, key): re-registering an endpoint\n // must not mint a second URL for something a provider already knows.\n await db.schema\n .createIndex(\"webhook_endpoints_owner\")\n .ifNotExists()\n .on(\"webhook_endpoints\")\n .columns([\"namespace\", \"endpoint\", \"owner_key\"])\n .unique()\n .execute();\n\n await db.schema\n .createTable(\"webhook_deliveries\")\n .ifNotExists()\n .addColumn(\"token\", \"text\", (col) => col.notNull())\n .addColumn(\"dedupe_key\", \"text\", (col) => col.notNull())\n .addColumn(\"seen_at\", \"text\", (col) => col.notNull())\n .addColumn(\"claim_id\", \"text\", (col) => col.notNull())\n .execute();\n\n await db.schema\n .createIndex(\"webhook_deliveries_key\")\n .ifNotExists()\n .on(\"webhook_deliveries\")\n .columns([\"token\", \"dedupe_key\"])\n .unique()\n .execute();\n\n // Every delivery prunes by `seen_at`; unindexed that is a scan of the\n // whole table, growing with it.\n await db.schema\n .createIndex(\"webhook_deliveries_seen_at\")\n .ifNotExists()\n .on(\"webhook_deliveries\")\n .columns([\"seen_at\"])\n .execute();\n\n this.#db = db;\n }\n\n get #handle(): IRelationalDb<Schema> {\n if (!this.#db) throw new Error(\"Webhook store used before init()\");\n return this.#db;\n }\n\n async ensure(\n namespace: string,\n endpoint: string,\n ownerKey: string,\n ): Promise<WebhookEndpointRow> {\n const existing = await this.#handle\n .selectFrom(\"webhook_endpoints\")\n .selectAll()\n .where(\"namespace\", \"=\", namespace)\n .where(\"endpoint\", \"=\", endpoint)\n .where(\"owner_key\", \"=\", ownerKey)\n .executeTakeFirst();\n if (existing) return toRow(existing);\n\n const row: Schema[\"webhook_endpoints\"] = {\n token: newWebhookToken(),\n namespace,\n endpoint,\n owner_key: ownerKey,\n created_at: new Date().toISOString(),\n };\n\n await this.#handle\n .insertInto(\"webhook_endpoints\")\n .values(row)\n // Two hosts arming the same endpoint at once must agree on one token.\n .onConflict((oc) =>\n oc.columns([\"namespace\", \"endpoint\", \"owner_key\"]).doNothing(),\n )\n .execute();\n\n const settled = await this.#handle\n .selectFrom(\"webhook_endpoints\")\n .selectAll()\n .where(\"namespace\", \"=\", namespace)\n .where(\"endpoint\", \"=\", endpoint)\n .where(\"owner_key\", \"=\", ownerKey)\n .executeTakeFirst();\n\n return settled ? toRow(settled) : toRow(row);\n }\n\n async find(token: string): Promise<WebhookEndpointRow | undefined> {\n if (!TOKEN_PATTERN.test(token)) return undefined;\n const found = await this.#handle\n .selectFrom(\"webhook_endpoints\")\n .selectAll()\n .where(\"token\", \"=\", token)\n .executeTakeFirst();\n return found ? toRow(found) : undefined;\n }\n\n async list(\n namespace: string,\n endpoint?: string,\n ): Promise<WebhookEndpointRow[]> {\n let query = this.#handle\n .selectFrom(\"webhook_endpoints\")\n .selectAll()\n .where(\"namespace\", \"=\", namespace);\n if (endpoint) query = query.where(\"endpoint\", \"=\", endpoint);\n return (await query.execute()).map(toRow);\n }\n\n async revoke(\n namespace: string,\n endpoint: string,\n ownerKey: string,\n ): Promise<void> {\n await this.#handle\n .deleteFrom(\"webhook_endpoints\")\n .where(\"namespace\", \"=\", namespace)\n .where(\"endpoint\", \"=\", endpoint)\n .where(\"owner_key\", \"=\", ownerKey)\n .execute();\n }\n\n async seen(token: string, key: string, ttlSeconds: number): Promise<boolean> {\n const now = Date.now();\n const cutoff = new Date(now - ttlSeconds * 1000).toISOString();\n\n // Prune first, so a key that has aged out is redeliverable rather than\n // rejected forever.\n await this.#handle\n .deleteFrom(\"webhook_deliveries\")\n .where(\"seen_at\", \"<\", cutoff)\n .execute();\n\n // Insert-then-read-back rather than trusting an affected-row count: what\n // \"on conflict do nothing\" reports differs by driver, and reading it wrong\n // means either every delivery looks like a redelivery or none does. The\n // claim id settles it without a transaction, so two hosts racing the same\n // delivery still agree on which one runs it.\n const claimId = randomBytes(16).toString(\"hex\");\n await this.#handle\n .insertInto(\"webhook_deliveries\")\n .values({\n token,\n dedupe_key: key,\n seen_at: new Date(now).toISOString(),\n claim_id: claimId,\n })\n .onConflict((oc) => oc.columns([\"token\", \"dedupe_key\"]).doNothing())\n .execute();\n\n const settled = await this.#handle\n .selectFrom(\"webhook_deliveries\")\n .select(\"claim_id\")\n .where(\"token\", \"=\", token)\n .where(\"dedupe_key\", \"=\", key)\n .executeTakeFirst();\n\n // Our claim stands: this is the first delivery. Anyone else's: a retry.\n return settled?.claim_id !== claimId;\n }\n}\n\nfunction toRow(row: Schema[\"webhook_endpoints\"]): WebhookEndpointRow {\n return {\n token: row.token,\n namespace: row.namespace,\n endpoint: row.endpoint,\n ownerKey: row.owner_key,\n createdAt: row.created_at,\n };\n}\n\n/** In-memory store, for hosts with no relational database and for tests. */\nexport class MemoryWebhookStore implements IWebhookStore {\n readonly #byToken = new Map<string, WebhookEndpointRow>();\n readonly #deliveries = new Map<string, number>();\n\n init(): Promise<void> {\n return Promise.resolve();\n }\n\n ensure(\n namespace: string,\n endpoint: string,\n ownerKey: string,\n ): Promise<WebhookEndpointRow> {\n for (const row of this.#byToken.values()) {\n if (\n row.namespace === namespace &&\n row.endpoint === endpoint &&\n row.ownerKey === ownerKey\n ) {\n return Promise.resolve(row);\n }\n }\n const row: WebhookEndpointRow = {\n token: newWebhookToken(),\n namespace,\n endpoint,\n ownerKey,\n createdAt: new Date().toISOString(),\n };\n this.#byToken.set(row.token, row);\n return Promise.resolve(row);\n }\n\n find(token: string): Promise<WebhookEndpointRow | undefined> {\n return Promise.resolve(this.#byToken.get(token));\n }\n\n list(namespace: string, endpoint?: string): Promise<WebhookEndpointRow[]> {\n return Promise.resolve(\n [...this.#byToken.values()].filter(\n (row) =>\n row.namespace === namespace &&\n (endpoint === undefined || row.endpoint === endpoint),\n ),\n );\n }\n\n revoke(namespace: string, endpoint: string, ownerKey: string): Promise<void> {\n for (const [token, row] of this.#byToken) {\n if (\n row.namespace === namespace &&\n row.endpoint === endpoint &&\n row.ownerKey === ownerKey\n ) {\n this.#byToken.delete(token);\n }\n }\n return Promise.resolve();\n }\n\n seen(token: string, key: string, ttlSeconds: number): Promise<boolean> {\n const now = Date.now();\n for (const [k, at] of this.#deliveries) {\n if (at < now - ttlSeconds * 1000) this.#deliveries.delete(k);\n }\n const composite = `${token}|${key}`;\n if (this.#deliveries.has(composite)) return Promise.resolve(true);\n this.#deliveries.set(composite, now);\n return Promise.resolve(false);\n }\n}\n","import {\n buildSubgraphSchema,\n type GraphQLResolverMap,\n type GraphQLSchemaModule,\n} from \"@apollo/subgraph\";\nimport { typeDefs as scalarsTypeDefs } from \"@powerhousedao/document-engineering/graphql\";\nimport type { Context } from \"@powerhousedao/reactor-api\";\nimport type {\n DocumentModelGlobalState,\n DocumentModelModule,\n} from \"@powerhousedao/shared/document-model\";\nimport { camelCase, pascalCase } from \"change-case\";\nimport { childLogger } from \"document-model\";\nimport { type DocumentNode, Kind, parse, print } from \"graphql\";\nimport { gql } from \"graphql-tag\";\nimport { GraphQLJSON, GraphQLJSONObject } from \"graphql-type-json\";\n\nconst logger = childLogger([\"reactor-api\", \"create-schema\"]);\n\n/**\n * Revision type - matches the definition in reactor/schema.graphql.\n * Used by PHDocument and document mutation results.\n */\nconst RevisionType = `\n type Revision {\n scope: String!\n revision: Int!\n }\n`;\n\n/**\n * Strip scalar definitions from a DocumentNode to avoid duplicates\n * when combining with other schemas that define the same scalars.\n */\nconst stripScalarDefinitions = (doc: DocumentNode): string => {\n const filteredDefinitions = doc.definitions.filter(\n (def) => def.kind !== Kind.SCALAR_TYPE_DEFINITION,\n );\n return print({ kind: Kind.DOCUMENT, definitions: filteredDefinitions });\n};\n\n/**\n * Type-system definition kinds that GraphQL requires to be uniquely named.\n * A subgraph SDL with two definitions sharing a name fails federation\n * composition (\"There can be only one type named X\"), which is fatal to the\n * whole gateway. We dedupe these by name; field/operation/extension nodes are\n * left untouched.\n */\nconst TYPE_DEFINITION_KINDS = new Set<Kind>([\n Kind.OBJECT_TYPE_DEFINITION,\n Kind.ENUM_TYPE_DEFINITION,\n Kind.INPUT_OBJECT_TYPE_DEFINITION,\n Kind.INTERFACE_TYPE_DEFINITION,\n Kind.UNION_TYPE_DEFINITION,\n Kind.SCALAR_TYPE_DEFINITION,\n]);\n\n/**\n * Drop duplicate type-system definitions by name, keeping the first occurrence.\n * Deduping is by name across ALL kinds (a `type` and an `enum` sharing a name\n * collide in GraphQL too), so the first definition of a given name wins\n * regardless of kind. State types are emitted before operation types, so\n * keep-first preserves the authoritative state definition. This heals a document\n * model that defines the same name twice (global+local, state+operation, or\n * twice in one scope) so the assembled subgraph SDL composes instead of crashing\n * the gateway (Sentry #917).\n */\nconst dedupeTypeDefinitions = (doc: DocumentNode): DocumentNode => {\n const seen = new Set<string>();\n const definitions = doc.definitions.filter((def) => {\n if (!TYPE_DEFINITION_KINDS.has(def.kind)) return true;\n const name = (def as { name?: { value: string } }).name?.value;\n if (!name) return true;\n if (seen.has(name)) {\n // A duplicate here would otherwise crash supergraph composition; log it so\n // production has a breadcrumb of which model shipped a duplicate name.\n logger.debug(`Dropping duplicate type definition: ${name}`);\n return false;\n }\n seen.add(name);\n return true;\n });\n return { kind: Kind.DOCUMENT, definitions };\n};\n\nexport const buildSubgraphSchemaModule = (\n documentModels: DocumentModelModule[],\n resolvers: GraphQLResolverMap<Context>,\n typeDefs: DocumentNode,\n): GraphQLSchemaModule => {\n const newResolvers = {\n ...resolvers,\n JSONObject: GraphQLJSONObject,\n Unknown: GraphQLJSON,\n };\n\n return {\n typeDefs: getDocumentModelTypeDefs(documentModels, typeDefs),\n resolvers: newResolvers,\n };\n};\nexport const createSchema = (\n documentModels: DocumentModelModule[],\n resolvers: GraphQLResolverMap<Context>,\n typeDefs: DocumentNode,\n) => {\n // Array form: @apollo/subgraph 2.15 dropped the bare-module overload.\n return buildSubgraphSchema([\n buildSubgraphSchemaModule(documentModels, resolvers, typeDefs),\n ]);\n};\n\n/**\n * Create a merged GraphQL schema from multiple subgraph modules.\n * Uses buildSubgraphSchema's array overload to combine type definitions\n * and resolvers from multiple subgraphs into a single executable schema.\n */\nexport const createMergedSchema = (modules: GraphQLSchemaModule[]) => {\n return buildSubgraphSchema(modules);\n};\n\nexport function getDocumentModelSchemaName(\n documentModel: DocumentModelGlobalState,\n) {\n return pascalCase(documentModel.name.replaceAll(\"/\", \" \"));\n}\n\nexport const getDocumentModelTypeDefs = (\n documentModels: DocumentModelModule[],\n typeDefs: DocumentNode,\n) => {\n let dmSchema = \"\";\n\n const addedDocumentModels = new Set<string>();\n documentModels.forEach(({ documentModel }) => {\n const dmSchemaName = getDocumentModelSchemaName(documentModel.global);\n if (addedDocumentModels.has(dmSchemaName)) {\n logger.debug(\n `Skipping document model with duplicate name: ${dmSchemaName}`,\n );\n return;\n }\n addedDocumentModels.add(dmSchemaName);\n // Use only the latest specification to avoid duplicate type definitions\n // when a document model has multiple versions (e.g. v1, v2).\n const latestSpec = documentModel.global.specifications.at(-1);\n const globalSchema = latestSpec?.state.global.schema ?? \"\";\n const localSchema = latestSpec?.state.local.schema ?? \"\";\n let tmpDmSchema = `\n ${globalSchema\n .replaceAll(\"scalar DateTime\", \"\")\n .replaceAll(/input (.*?) {[\\s\\S]*?}/g, \"\")};\n\n ${localSchema\n .replaceAll(\"scalar DateTime\", \"\")\n .replaceAll(/input (.*?) {[\\s\\S]*?}/g, \"\")\n .replaceAll(\"type AccountSnapshotLocalState\", \"\")\n .replaceAll(\"type BudgetStatementLocalState\", \"\")\n .replaceAll(\"type ScopeFrameworkLocalState\", \"\")};\n\n \\n`;\n\n const found = tmpDmSchema.match(\n /(type|enum|union|interface)\\s+(\\w+)[\\s{]/g,\n );\n const trimmedFound = found?.map((f) =>\n f\n .replaceAll(\"type \", \"\")\n .replaceAll(\"enum \", \"\")\n .replaceAll(\"union \", \"\")\n .replaceAll(\"interface \", \"\")\n .replaceAll(\"{\", \"\")\n .trim(),\n );\n trimmedFound?.forEach((f) => {\n // Create a regex that matches the type name with proper boundaries\n const typeRegex = new RegExp(\n // Match type references in various GraphQL contexts\n `(?<![_A-Za-z0-9])(${f})(?![_A-Za-z0-9])|` + // Basic type references\n `\\\\[(${f})\\\\]|` + // Array types without nullability\n `\\\\[(${f})!\\\\]|` + // Array of non-null types\n `\\\\[(${f})\\\\]!|` + // Non-null array of types\n `\\\\[(${f})!\\\\]!`, // Non-null array of non-null types\n \"g\",\n );\n\n tmpDmSchema = tmpDmSchema.replace(\n typeRegex,\n (\n match: string,\n p1: string,\n p2: string,\n p3: string,\n p4: string,\n p5: string,\n ) => {\n // If it's an array type, preserve the brackets and ! while replacing the type name\n if (match.startsWith(\"[\")) {\n return match.replace(\n p2 || p3 || p4 || p5,\n `${dmSchemaName}_${p2 || p3 || p4 || p5}`,\n );\n }\n // Basic type reference\n return `${dmSchemaName}_${p1}`;\n },\n );\n });\n dmSchema += tmpDmSchema;\n dmSchema += `\n type ${dmSchemaName} implements IDocument {\n id: String!\n name: String!\n documentType: String!\n operations(skip: Int, first: Int): [Operation!]!\n revision: Int!\n createdAtUtcIso: DateTime!\n lastModifiedAtUtcIso: DateTime!\n ${dmSchemaName !== \"DocumentModel\" ? `initialState: ${dmSchemaName}_${dmSchemaName}State!` : \"\"}\n ${dmSchemaName !== \"DocumentModel\" ? `state: ${dmSchemaName}_${dmSchemaName}State!` : \"\"}\n stateJSON: JSONObject\n }\\n`;\n });\n\n // add the mutation and query types\n const schema = gql`\n scalar JSONObject\n scalar AttachmentRef\n # Codegen scalars not in the document-engineering set.\n scalar Unknown\n scalar Address\n ${scalarsTypeDefs.join(\"\\n\").replaceAll(\";\", \"\")}\n\n type PHOperationContext {\n signer: Signer\n }\n\n type Signer {\n user: SignerUser\n app: SignerApp\n signatures: [String!]!\n }\n\n type SignerUser {\n address: String!\n networkId: String!\n chainId: Int!\n }\n\n type SignerApp {\n name: String!\n key: String!\n }\n\n type Operation {\n id: String!\n type: String!\n index: Int!\n timestampUtcMs: DateTime!\n hash: String!\n skip: Int\n inputText: String\n error: String\n context: PHOperationContext\n }\n\n interface IDocument {\n id: String!\n name: String!\n documentType: String!\n revision: Int!\n createdAtUtcIso: DateTime!\n lastModifiedAtUtcIso: DateTime!\n operations(first: Int, skip: Int): [Operation!]!\n stateJSON: JSONObject\n }\n ${dmSchema.replaceAll(\";\", \"\")}\n\n type GqlDocument implements IDocument {\n id: String!\n name: String!\n documentType: String!\n revision: Int!\n createdAtUtcIso: DateTime!\n lastModifiedAtUtcIso: DateTime!\n operations(first: Int, skip: Int): [Operation!]!\n stateJSON: JSONObject\n }\n\n type DriveDocument implements IDocument {\n id: String!\n name: String!\n documentType: String!\n revision: Int!\n createdAtUtcIso: DateTime!\n lastModifiedAtUtcIso: DateTime!\n operations(first: Int, skip: Int): [Operation!]!\n stateJSON: JSONObject\n }\n\n ${stripScalarDefinitions(typeDefs)}\n `;\n\n return dedupeTypeDefinitions(schema);\n};\n\n/**\n * Extract type names from a GraphQL schema.\n * @param {string} schema - GraphQL schema string\n * @returns {string[]} Array of type names\n */\nfunction extractTypeNames(schema: string) {\n const found = schema.match(/(type|enum|union|interface|input)\\s+(\\w+)[\\s{]/g);\n if (!found) return [];\n return found.map((f) =>\n f\n .replaceAll(\"type \", \"\")\n .replaceAll(\"enum \", \"\")\n .replaceAll(\"union \", \"\")\n .replaceAll(\"interface \", \"\")\n .replaceAll(\"input \", \"\")\n .replaceAll(\"{\", \"\")\n .trim(),\n );\n}\n\n/**\n * Extract input type definitions from a GraphQL schema.\n * @param {string} schema - GraphQL schema string\n * @param {Set<string>} excludeTypeNames - Type names to exclude from extraction\n * @returns {string} All input type definitions as a string\n */\nfunction extractInputTypeDefinitions(\n schema: string,\n excludeTypeNames: Set<string> = new Set(),\n): string {\n // Match input type blocks: input TypeName { ... }\n const inputTypeRegex = /input\\s+(\\w+)\\s*\\{[^}]*\\}/g;\n const matches: string[] = [];\n let match;\n while ((match = inputTypeRegex.exec(schema)) !== null) {\n const typeName = match[1];\n // Skip if this type name is in the exclusion set\n if (!excludeTypeNames.has(typeName)) {\n matches.push(match[0]);\n }\n }\n if (matches.length === 0) return \"\";\n return matches.join(\"\\n\\n\");\n}\n\n/**\n * AST type node shape for recursive type conversion.\n */\ntype GraphQLTypeNode = {\n kind: Kind;\n name?: { value: string };\n type?: GraphQLTypeNode;\n};\n\n/**\n * Extract the root state type name from a scope's GraphQL schema.\n * Uses the naming convention: {DocumentName}State for global,\n * {DocumentName}{PascalScope}State for other scopes (e.g., DocumentDriveLocalState).\n * Falls back to the last ObjectTypeDefinition (root types are conventionally last).\n */\nfunction extractRootTypeName(\n schema: string,\n documentName: string,\n scopeName: string,\n): string | null {\n try {\n const ast = parse(schema);\n\n // Try conventions:\n // 1. {DocumentName}State for global, {DocumentName}{Scope}State otherwise\n // 2. {DocumentName}GlobalState (DocumentModel uses this variant)\n const scopeSuffix = scopeName === \"global\" ? \"\" : pascalCase(scopeName);\n const candidates = [\n `${documentName}${scopeSuffix}State`,\n `${documentName}${pascalCase(scopeName)}State`,\n ];\n\n let lastObjectType: string | null = null;\n for (const def of ast.definitions) {\n if (def.kind === Kind.OBJECT_TYPE_DEFINITION) {\n if (candidates.includes(def.name.value)) {\n return def.name.value;\n }\n lastObjectType = def.name.value;\n }\n }\n\n // Fallback: last object type (root state types are defined last by convention)\n return lastObjectType;\n } catch {\n // ignore parse errors\n }\n return null;\n}\n\n/**\n * Convert a GraphQL output type AST node to an optional input type string.\n * Strips non-null markers and converts object type references to Input suffix.\n */\nfunction convertTypeNodeToInput(\n typeNode: GraphQLTypeNode,\n objectNames: Set<string>,\n unionNames: Set<string>,\n interfaceNames: Set<string>,\n): string {\n if (typeNode.kind === Kind.NON_NULL_TYPE && typeNode.type) {\n return convertTypeNodeToInput(\n typeNode.type,\n objectNames,\n unionNames,\n interfaceNames,\n );\n }\n if (typeNode.kind === Kind.LIST_TYPE && typeNode.type) {\n const inner = convertTypeNodeToInput(\n typeNode.type,\n objectNames,\n unionNames,\n interfaceNames,\n );\n return `[${inner}]`;\n }\n if (typeNode.kind === Kind.NAMED_TYPE && typeNode.name) {\n const name = typeNode.name.value;\n if (objectNames.has(name)) return `${name}Input`;\n if (unionNames.has(name) || interfaceNames.has(name)) return \"JSONObject\";\n return name;\n }\n return \"JSONObject\";\n}\n\n/**\n * Generate GraphQL input type definitions from a state schema string.\n * Converts output type definitions to input types with all fields optional.\n * - Object type references get Input suffix\n * - Union/interface references become JSONObject\n * - Enums and scalars remain unchanged\n */\nfunction generateStateInputTypes(\n stateSchema: string,\n excludeTypeNames?: Set<string>,\n): string {\n if (!stateSchema || !stateSchema.trim()) return \"\";\n\n let ast;\n try {\n ast = parse(stateSchema);\n } catch {\n return \"\";\n }\n\n const enumNames = new Set<string>();\n const unionNames = new Set<string>();\n const interfaceNames = new Set<string>();\n const objectNames = new Set<string>();\n const existingInputNames = new Set<string>();\n\n for (const def of ast.definitions) {\n switch (def.kind) {\n case Kind.ENUM_TYPE_DEFINITION:\n enumNames.add(def.name.value);\n break;\n case Kind.UNION_TYPE_DEFINITION:\n unionNames.add(def.name.value);\n break;\n case Kind.INTERFACE_TYPE_DEFINITION:\n interfaceNames.add(def.name.value);\n break;\n case Kind.OBJECT_TYPE_DEFINITION:\n objectNames.add(def.name.value);\n break;\n case Kind.INPUT_OBJECT_TYPE_DEFINITION:\n existingInputNames.add(def.name.value);\n break;\n }\n }\n\n const inputTypes: string[] = [];\n\n for (const def of ast.definitions) {\n if (def.kind !== Kind.OBJECT_TYPE_DEFINITION) continue;\n // Skip if an input type with the same name already exists in the schema\n // or in operation schemas (to avoid duplicates with moduleSchemas)\n const inputName = `${def.name.value}Input`;\n if (existingInputNames.has(inputName)) continue;\n if (excludeTypeNames?.has(inputName)) continue;\n const fields = def.fields ?? [];\n if (fields.length === 0) continue;\n\n const inputFields = fields.map((field) => {\n const fieldName = field.name.value;\n const fieldType = convertTypeNodeToInput(\n field.type as GraphQLTypeNode,\n objectNames,\n unionNames,\n interfaceNames,\n );\n return ` ${fieldName}: ${fieldType}`;\n });\n\n inputTypes.push(\n `input ${def.name.value}Input {\\n${inputFields.join(\"\\n\")}\\n}`,\n );\n }\n\n return inputTypes.join(\"\\n\\n\");\n}\n\n/**\n * Apply type prefixes to GraphQL schema to namespace types and avoid collisions.\n * Inlined from @powerhousedao/common/utils to avoid ES module import issues.\n * @param {string} schema - GraphQL schema string\n * @param {string} prefix - Prefix to apply to type names\n * @param {string[]} externalTypeNames - Type names from other schemas to also prefix\n * @returns {string} Schema with prefixed types\n */\nfunction applyGraphQLTypePrefixes(\n schema: string,\n prefix: string,\n externalTypeNames: string[] = [],\n): string {\n if (!schema || !schema.trim()) {\n return schema;\n }\n\n let processedSchema = schema;\n\n // Find types defined in this schema\n const localTypeNames = extractTypeNames(schema);\n\n // Combine with external type names (remove duplicates)\n const allTypeNames = [...new Set([...localTypeNames, ...externalTypeNames])];\n\n if (allTypeNames.length === 0) {\n return schema;\n }\n\n allTypeNames.forEach((typeName) => {\n const typeRegex = new RegExp(\n // Match type references in various GraphQL contexts\n `(?<![_A-Za-z0-9])(${typeName})(?![_A-Za-z0-9])|` +\n `\\\\[(${typeName})\\\\]|` +\n `\\\\[(${typeName})!\\\\]|` +\n `\\\\[(${typeName})\\\\]!|` +\n `\\\\[(${typeName})!\\\\]!`,\n \"g\",\n );\n\n processedSchema = processedSchema.replace(\n typeRegex,\n (match, p1, p2, p3, p4, p5) => {\n if (match.startsWith(\"[\")) {\n return match.replace(\n (p2 || p3 || p4 || p5) as string,\n `${prefix}_${p2 || p3 || p4 || p5}`,\n );\n }\n // Basic type reference\n return `${prefix}_${p1}`;\n },\n );\n });\n\n return processedSchema;\n}\n\n/**\n * Options for generating document model GraphQL schemas.\n */\nexport interface DocumentModelSchemaOptions {\n /**\n * When true, generates new API patterns:\n * - Mutations return full document objects (MutationResult type)\n * - Adds createEmptyDocument mutation\n * - Makes docId and input parameters required\n * @default false\n */\n useNewApi?: boolean;\n}\n\n/**\n * Generate a GraphQL schema for a document model.\n *\n * @param documentModel - The document model global state\n * @param options - Schema generation options\n * @returns GraphQL DocumentNode\n */\nexport function generateDocumentModelSchema(\n documentModel: DocumentModelGlobalState,\n options: DocumentModelSchemaOptions = {},\n): DocumentNode {\n const { useNewApi = false } = options;\n\n const specification = documentModel.specifications.at(-1);\n const documentName = getDocumentModelSchemaName(documentModel);\n const globalStateSchema = specification?.state.global.schema;\n const localStateSchema = specification?.state.local.schema;\n const globalStateTypeNames = extractTypeNames(globalStateSchema ?? \"\");\n const localStateTypeNames = extractTypeNames(localStateSchema ?? \"\");\n const stateTypeNames = [...globalStateTypeNames, ...localStateTypeNames];\n\n // Collect ALL type names from all operations' schemas\n const allOperationTypeNames =\n specification?.modules.flatMap((module) =>\n module.operations.flatMap((op) => extractTypeNames(op.schema ?? \"\")),\n ) ?? [];\n\n // Combine state types and all operation types for prefixing\n const allTypeNames = [\n ...new Set([...stateTypeNames, ...allOperationTypeNames]),\n ];\n\n // Extract input type definitions from state schema, excluding operation-specific inputs\n // (those are already defined in op.schema)\n const operationInputTypeNames = new Set(allOperationTypeNames);\n const stateInputTypes = extractInputTypeDefinitions(\n globalStateSchema ?? \"\",\n operationInputTypeNames,\n );\n const prefixedStateInputTypes = applyGraphQLTypePrefixes(\n stateInputTypes,\n documentName,\n allTypeNames,\n );\n\n // Helper to check if schema has actual GraphQL type definitions\n const hasValidSchema = (schema: string | null | undefined): boolean =>\n !!(schema && /\\b(input|type|enum|union|interface)\\s+\\w+/.test(schema));\n\n // Process state schema types (remove input types, clean up, and prefix)\n const stateSchemaTypes = globalStateSchema\n ? applyGraphQLTypePrefixes(\n globalStateSchema\n .replaceAll(\"scalar DateTime\", \"\")\n .replaceAll(/input (.*?) {[\\s\\S]*?}/g, \"\"),\n documentName,\n allTypeNames,\n )\n : \"\";\n\n if (useNewApi) {\n // New API: flat queries, typed state, async mutations\n return generateNewApiSchema(\n documentName,\n specification,\n stateSchemaTypes,\n prefixedStateInputTypes,\n allTypeNames,\n hasValidSchema,\n );\n }\n\n // Legacy API\n return generateLegacyApiSchema(\n documentName,\n specification,\n prefixedStateInputTypes,\n allTypeNames,\n hasValidSchema,\n );\n}\n\n/**\n * Generate legacy API schema with nested queries\n */\nfunction generateLegacyApiSchema(\n documentName: string,\n specification: DocumentModelGlobalState[\"specifications\"][0] | undefined,\n prefixedStateInputTypes: string,\n allTypeNames: string[],\n hasValidSchema: (schema: string | null | undefined) => boolean,\n): DocumentNode {\n const createDocumentMutation = `${documentName}_createDocument(name:String!, driveId:String): String`;\n\n const operationMutations =\n specification?.modules\n .flatMap((module) =>\n module.operations\n .filter((op) => op.name && hasValidSchema(op.schema))\n .map(\n (op) =>\n `${documentName}_${camelCase(op.name!)}(\n driveId: String, docId: PHID, input: ${documentName}_${pascalCase(op.name!)}Input): Int`,\n ),\n )\n .join(\"\\n \") ?? \"\";\n\n const moduleSchemas =\n specification?.modules\n .filter((module) =>\n module.operations.some((op) => hasValidSchema(op.schema)),\n )\n .map(\n (module) =>\n `\"\"\"\n Module: ${pascalCase(module.name)}\n \"\"\"\n ${module.operations\n .filter((op) => hasValidSchema(op.schema))\n .map((op) =>\n applyGraphQLTypePrefixes(\n op.schema ?? \"\",\n documentName,\n allTypeNames,\n ),\n )\n .join(\"\\n \")}`,\n )\n .join(\"\\n\") ?? \"\";\n\n return gql`\n \"\"\"\n Queries: ${documentName} Document\n \"\"\"\n\n type ${documentName}Queries {\n getDocument(docId: PHID!, driveId: PHID): ${documentName}\n getDocuments(driveId: String!): [${documentName}!]\n }\n\n type Query {\n ${documentName}: ${documentName}Queries\n }\n\n \"\"\"\n Mutations: ${documentName}\n \"\"\"\n type Mutation {\n ${createDocumentMutation}\n\n ${operationMutations}\n }\n\n ${\n prefixedStateInputTypes\n ? `\"\"\"\n Input Types from State Schema\n \"\"\"\n ${prefixedStateInputTypes}`\n : \"\"\n }\n\n ${moduleSchemas}`;\n}\n\n/**\n * Generate new API schema with flat queries, typed state, and async mutations.\n * Note: State schema types are NOT included here because they are already defined\n * in getDocumentModelTypeDefs() which is used during schema composition.\n * Including them here would cause duplicate type definitions.\n */\nfunction generateNewApiSchema(\n documentName: string,\n specification: DocumentModelGlobalState[\"specifications\"][0] | undefined,\n _stateSchemaTypes: string,\n prefixedStateInputTypes: string,\n allTypeNames: string[],\n hasValidSchema: (schema: string | null | undefined) => boolean,\n): DocumentNode {\n // Use full state type for all document models\n const stateType = `${documentName}_FullState!`;\n\n // Shared base types for document state structure (same for all document types)\n const sharedBaseTypes = `\n \"\"\"Hash configuration for document state\"\"\"\n type ${documentName}_PHHashConfig {\n algorithm: String!\n encoding: String!\n }\n\n \"\"\"Document scope state (same for all document types)\"\"\"\n type ${documentName}_PHDocumentScopeState {\n version: Int!\n hash: ${documentName}_PHHashConfig!\n isDeleted: Boolean\n deletedAtUtcIso: String\n deletedBy: String\n deletionReason: String\n }\n `;\n\n // Full state type with all scopes (auth, document, global, local)\n // Note: DocumentModel uses different naming convention (GlobalState suffix instead of State)\n // For local state, check if the specification defines a local state type\n const localSchema = specification?.state.local.schema ?? \"\";\n const hasLocalStateType = localSchema.includes(\n `type ${documentName}LocalState`,\n );\n\n const globalStateType =\n documentName === \"DocumentModel\"\n ? `${documentName}_${documentName}GlobalState!`\n : `${documentName}_${documentName}State!`;\n const localStateType = !hasLocalStateType\n ? \"JSONObject!\"\n : `${documentName}_${documentName}LocalState!`;\n\n const fullStateType = `\n \"\"\"Full state with all scopes for ${documentName}\"\"\"\n type ${documentName}_FullState {\n auth: JSONObject!\n document: ${documentName}_PHDocumentScopeState!\n global: ${globalStateType}\n local: ${localStateType}\n }\n `;\n\n // Common input types - use extend to avoid conflicts with other subgraphs\n const commonInputTypes = `\n input ${documentName}_ViewFilterInput {\n branch: String\n scopes: [String!]\n }\n\n input ${documentName}_PagingInput {\n limit: Int\n offset: Int\n cursor: String\n }\n\n input ${documentName}_SearchFilterInput {\n parentId: String\n identifiers: [String!]\n }\n `;\n\n // Revision type - imported from shared-schema.ts for consistency with ReactorSubgraph\n // Must be defined in each subgraph for Apollo Federation\n const revisionType = RevisionType;\n\n // Result types with typed state (or JSONObject for DocumentModel)\n // The state type (${documentName}_${documentName}State) is defined in getDocumentModelTypeDefs()\n // Uses revisionsList with shared Revision type to match ReactorSubgraph pattern\n const resultTypes = `\n \"\"\"\n Mutation result type for ${documentName} operations with typed state.\n Matches ReactorSubgraph PHDocument pattern with revisionsList.\n \"\"\"\n type ${documentName}MutationResult {\n id: String!\n slug: String\n preferredEditor: String\n name: String!\n documentType: String!\n state: ${stateType}\n revisionsList: [Revision!]!\n createdAtUtcIso: DateTime!\n lastModifiedAtUtcIso: DateTime!\n }\n\n \"\"\"\n Document with children for ${documentName}\n \"\"\"\n type ${documentName}_DocumentWithChildren {\n document: ${documentName}MutationResult!\n childIds: [String!]!\n }\n\n \"\"\"\n Paginated result type for ${documentName} documents\n \"\"\"\n type ${documentName}_DocumentResultPage {\n items: [${documentName}MutationResult!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n }\n `;\n\n // Queries nested under ${documentName} namespace\n const queries = `\n type ${documentName}Queries {\n \"\"\"Get a specific ${documentName} document by identifier\"\"\"\n document(identifier: String!, view: ${documentName}_ViewFilterInput): ${documentName}_DocumentWithChildren\n\n \"\"\"Get all ${documentName} documents (paged)\"\"\"\n documents(paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!\n\n \"\"\"Find ${documentName} documents by search criteria\"\"\"\n findDocuments(search: ${documentName}_SearchFilterInput, view: ${documentName}_ViewFilterInput, paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!\n\n \"\"\"Get outgoing relationships of a ${documentName} document\"\"\"\n documentOutgoingRelationships(sourceIdentifier: String!, relationshipType: String!, view: ${documentName}_ViewFilterInput, paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!\n\n \"\"\"Get incoming relationships to a ${documentName} document\"\"\"\n documentIncomingRelationships(targetIdentifier: String!, relationshipType: String!, view: ${documentName}_ViewFilterInput, paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!\n }\n `;\n\n // Generate initial state input types for each scope\n let initialStateInputSchema = \"\";\n if (specification) {\n const scopeFields: string[] = [];\n const generatedInputTypeParts: string[] = [];\n\n for (const [scopeName, scopeState] of Object.entries(specification.state)) {\n const schema = (scopeState as { schema?: string }).schema ?? \"\";\n if (hasValidSchema(schema)) {\n const rootTypeName = extractRootTypeName(\n schema,\n documentName,\n scopeName,\n );\n if (!rootTypeName) {\n scopeFields.push(` ${scopeName}: JSONObject`);\n continue;\n }\n const scopeInputTypes = generateStateInputTypes(\n schema,\n new Set(allTypeNames),\n );\n if (!scopeInputTypes) {\n scopeFields.push(` ${scopeName}: JSONObject`);\n continue;\n }\n const prefixedScopeInputTypes = applyGraphQLTypePrefixes(\n scopeInputTypes,\n documentName,\n allTypeNames,\n );\n scopeFields.push(\n ` ${scopeName}: ${documentName}_${rootTypeName}Input`,\n );\n generatedInputTypeParts.push(prefixedScopeInputTypes);\n } else {\n scopeFields.push(` ${scopeName}: JSONObject`);\n }\n }\n\n if (scopeFields.length > 0) {\n const inputTypeDefs = generatedInputTypeParts.join(\"\\n\\n\");\n const wrapper = `input ${documentName}_InitialStateInput {\\n${scopeFields.join(\"\\n\")}\\n}`;\n initialStateInputSchema = inputTypeDefs\n ? `${inputTypeDefs}\\n\\n${wrapper}`\n : wrapper;\n }\n }\n\n // Mutations nested under ${documentName} namespace\n const createDocumentMutation = initialStateInputSchema\n ? `createDocument(name: String!, parentIdentifier: String, slug: String, preferredEditor: String, initialState: ${documentName}_InitialStateInput): ${documentName}MutationResult!`\n : `createDocument(name: String!, parentIdentifier: String, preferredEditor: String): ${documentName}MutationResult!`;\n const createEmptyDocumentMutation = `createEmptyDocument(parentIdentifier: String): ${documentName}MutationResult!`;\n\n const operationMutations =\n specification?.modules\n .flatMap((module) =>\n module.operations\n .filter((op) => op.name && hasValidSchema(op.schema))\n .flatMap((op) => [\n // Sync mutation\n `${camelCase(op.name!)}(docId: PHID!, input: ${documentName}_${pascalCase(op.name!)}Input!): ${documentName}MutationResult!`,\n // Async mutation\n `${camelCase(op.name!)}Async(docId: PHID!, input: ${documentName}_${pascalCase(op.name!)}Input!): String!`,\n ]),\n )\n .join(\"\\n \") ?? \"\";\n\n const moduleSchemas =\n specification?.modules\n .filter((module) =>\n module.operations.some((op) => hasValidSchema(op.schema)),\n )\n .map(\n (module) =>\n `\"\"\"\n Module: ${pascalCase(module.name)}\n \"\"\"\n ${module.operations\n .filter((op) => hasValidSchema(op.schema))\n .map((op) =>\n applyGraphQLTypePrefixes(\n op.schema ?? \"\",\n documentName,\n allTypeNames,\n ),\n )\n .join(\"\\n \")}`,\n )\n .join(\"\\n\") ?? \"\";\n\n return gql`\n scalar DateTime\n scalar JSONObject\n scalar AttachmentRef\n\n ${revisionType}\n\n ${sharedBaseTypes}\n\n ${fullStateType}\n\n ${commonInputTypes}\n\n ${resultTypes}\n\n \"\"\"\n Queries: ${documentName} Document\n \"\"\"\n ${queries}\n\n \"\"\"\n Mutations: ${documentName}\n \"\"\"\n type ${documentName}Mutations {\n ${createDocumentMutation}\n ${createEmptyDocumentMutation}\n\n ${operationMutations}\n }\n\n type Query {\n ${documentName}: ${documentName}Queries!\n }\n\n type Mutation {\n ${documentName}: ${documentName}Mutations!\n }\n\n ${\n prefixedStateInputTypes\n ? `\"\"\"\n Input Types from State Schema\n \"\"\"\n ${prefixedStateInputTypes}`\n : \"\"\n }\n\n ${\n initialStateInputSchema\n ? `\"\"\"\n Input Types for Initial State\n \"\"\"\n ${initialStateInputSchema}`\n : \"\"\n }\n\n ${moduleSchemas}`;\n}\n","import type {\n GraphQLResolveInfo,\n GraphQLScalarType,\n GraphQLScalarTypeConfig,\n} from \"graphql\";\nimport type { Context } from \"../../types.js\";\nimport * as z from \"zod\";\nimport type { DocumentNode } from \"graphql\";\nimport { gql } from \"graphql-tag\";\nexport type Maybe<T> = T | null | undefined;\nexport type InputMaybe<T> = T | null | undefined;\nexport type Exact<T extends { [key: string]: unknown }> = {\n [K in keyof T]: T[K];\n};\nexport type MakeOptional<T, K extends keyof T> = Omit<T, K> & {\n [SubKey in K]?: Maybe<T[SubKey]>;\n};\nexport type MakeMaybe<T, K extends keyof T> = Omit<T, K> & {\n [SubKey in K]: Maybe<T[SubKey]>;\n};\nexport type MakeEmpty<\n T extends { [key: string]: unknown },\n K extends keyof T,\n> = { [_ in K]?: never };\nexport type Incremental<T> =\n | T\n | {\n [P in keyof T]?: P extends \" $fragmentName\" | \"__typename\" ? T[P] : never;\n };\nexport type RequireFields<T, K extends keyof T> = Omit<T, K> & {\n [P in K]-?: NonNullable<T[P]>;\n};\n/** All built-in and custom scalars, mapped to their actual values */\nexport type Scalars = {\n ID: { input: string; output: string };\n String: { input: string; output: string };\n Boolean: { input: boolean; output: boolean };\n Int: { input: number; output: number };\n Float: { input: number; output: number };\n DateTime: { input: string | Date; output: string | Date };\n JSONObject: { input: NonNullable<unknown>; output: NonNullable<unknown> };\n};\n\nexport type Action = {\n readonly context?: Maybe<ActionContext>;\n readonly id: Scalars[\"String\"][\"output\"];\n readonly input: Scalars[\"JSONObject\"][\"output\"];\n readonly scope: Scalars[\"String\"][\"output\"];\n readonly timestampUtcMs: Scalars[\"String\"][\"output\"];\n readonly type: Scalars[\"String\"][\"output\"];\n};\n\n/**\n * One operation an authorization preflight predicts a verdict for.\n *\n * `input` is what a conditional grant reads, so a candidate standing for a\n * filled-in form carries that form's input. Omitting it predicts the verdict an\n * empty input earns, not the verdict the filled-in form will get.\n */\nexport type ActionCandidateInput = {\n readonly input?: InputMaybe<Scalars[\"JSONObject\"][\"input\"]>;\n readonly scope: Scalars[\"String\"][\"input\"];\n readonly type: Scalars[\"String\"][\"input\"];\n};\n\nexport type ActionContext = {\n readonly signer?: Maybe<ReactorSigner>;\n};\n\n/**\n * An action's context, as a caller submits it.\n *\n * Declares every field `ActionContext` carries, because an input object rejects a\n * field it does not declare: an action stamped with the head it applies to - which\n * is what a signing client sends - is refused outright if these are missing, and\n * that refusal is a whole-request one, not a per-field one.\n *\n * `prevOpHash` and `prevOpIndex` are the scope head the action was composed\n * against. They are recorded rather than enforced; a signature is verified from\n * the params carried in its own tuple, which do not include them.\n */\nexport type ActionContextInput = {\n /** Covers replay of an operation that would otherwise be a no-op. */\n readonly nonce?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n /** The hash of the state the action applies to. */\n readonly prevOpHash?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n /** The index of the last operation in the scope the action applies to. */\n readonly prevOpIndex?: InputMaybe<Scalars[\"Int\"][\"input\"]>;\n readonly signer?: InputMaybe<ReactorSignerInput>;\n};\n\n/**\n * One candidate's predicted verdict. `reason` carries the refusal a DENY is\n * recorded with, and is null on an ALLOW.\n */\nexport type ActionEvaluation = {\n readonly decision: AuthDecision;\n readonly reason?: Maybe<Scalars[\"String\"][\"output\"]>;\n};\n\n/**\n * The predicted verdicts for a set of candidates, in the order they were given,\n * with the aggregates a caller branches on.\n *\n * The aggregates are redundant -- a verdict is binary -- and all four are returned\n * so a caller reads the one its question is phrased in rather than negating\n * another. Over no candidates every aggregate is false: nothing is allowed and\n * nothing is denied.\n */\nexport type ActionEvaluations = {\n readonly allAllowed: Scalars[\"Boolean\"][\"output\"];\n readonly allDenied: Scalars[\"Boolean\"][\"output\"];\n readonly anyAllowed: Scalars[\"Boolean\"][\"output\"];\n readonly anyDenied: Scalars[\"Boolean\"][\"output\"];\n readonly evaluations: ReadonlyArray<ActionEvaluation>;\n};\n\nexport type ActionInput = {\n readonly context?: InputMaybe<ActionContextInput>;\n readonly id: Scalars[\"String\"][\"input\"];\n readonly input: Scalars[\"JSONObject\"][\"input\"];\n readonly scope: Scalars[\"String\"][\"input\"];\n readonly timestampUtcMs: Scalars[\"String\"][\"input\"];\n readonly type: Scalars[\"String\"][\"input\"];\n};\n\nexport enum AuthDecision {\n Allow = \"ALLOW\",\n Deny = \"DENY\",\n}\n\nexport type ChannelMeta = {\n readonly id: Scalars[\"String\"][\"output\"];\n};\n\nexport type ChannelMetaInput = {\n readonly id: Scalars[\"String\"][\"input\"];\n};\n\nexport type DeadLetterInfo = {\n readonly branch: Scalars[\"String\"][\"output\"];\n readonly documentId: Scalars[\"String\"][\"output\"];\n readonly error: Scalars[\"String\"][\"output\"];\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 readonly errorType?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly jobId: Scalars[\"String\"][\"output\"];\n readonly operationCount: Scalars[\"Int\"][\"output\"];\n readonly scopes: ReadonlyArray<Scalars[\"String\"][\"output\"]>;\n};\n\nexport type DocumentChangeContext = {\n readonly childId?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly parentId?: Maybe<Scalars[\"String\"][\"output\"]>;\n};\n\nexport type DocumentChangeEvent = {\n readonly context?: Maybe<DocumentChangeContext>;\n readonly documents: ReadonlyArray<PhDocument>;\n readonly type: DocumentChangeType;\n};\n\nexport enum DocumentChangeType {\n ChildAdded = \"CHILD_ADDED\",\n ChildRemoved = \"CHILD_REMOVED\",\n Created = \"CREATED\",\n Deleted = \"DELETED\",\n ParentAdded = \"PARENT_ADDED\",\n ParentRemoved = \"PARENT_REMOVED\",\n Updated = \"UPDATED\",\n}\n\nexport type DocumentModelGlobalState = {\n readonly id: Scalars[\"String\"][\"output\"];\n readonly name: Scalars[\"String\"][\"output\"];\n readonly namespace?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly specification: Scalars[\"JSONObject\"][\"output\"];\n readonly version?: Maybe<Scalars[\"String\"][\"output\"]>;\n};\n\nexport type DocumentModelResultPage = {\n readonly cursor?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly hasNextPage: Scalars[\"Boolean\"][\"output\"];\n readonly hasPreviousPage: Scalars[\"Boolean\"][\"output\"];\n readonly items: ReadonlyArray<DocumentModelGlobalState>;\n};\n\nexport type DocumentOperationsFilterInput = {\n readonly actionTypes?: InputMaybe<ReadonlyArray<Scalars[\"String\"][\"input\"]>>;\n readonly branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly scopes?: InputMaybe<ReadonlyArray<Scalars[\"String\"][\"input\"]>>;\n readonly sinceRevision?: InputMaybe<Scalars[\"Int\"][\"input\"]>;\n readonly timestampFrom?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly timestampTo?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n};\n\nexport type DocumentRelationship = {\n readonly createdAt: Scalars[\"DateTime\"][\"output\"];\n readonly metadata?: Maybe<Scalars[\"JSONObject\"][\"output\"]>;\n readonly relationshipType: Scalars[\"String\"][\"output\"];\n readonly sourceId: Scalars[\"String\"][\"output\"];\n readonly targetId: Scalars[\"String\"][\"output\"];\n readonly updatedAt: Scalars[\"DateTime\"][\"output\"];\n};\n\nexport type DocumentRelationshipResultPage = {\n readonly cursor?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly hasNextPage: Scalars[\"Boolean\"][\"output\"];\n readonly hasPreviousPage: Scalars[\"Boolean\"][\"output\"];\n readonly items: ReadonlyArray<DocumentRelationship>;\n};\n\nexport type DocumentWithChildren = {\n readonly childIds: ReadonlyArray<Scalars[\"String\"][\"output\"]>;\n readonly document: PhDocument;\n};\n\nexport type JobChangeEvent = {\n readonly error?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly jobId: Scalars[\"String\"][\"output\"];\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 readonly result?: Maybe<Scalars[\"JSONObject\"][\"output\"]>;\n readonly status: Scalars[\"String\"][\"output\"];\n};\n\nexport type JobInfo = {\n readonly completedAt?: Maybe<Scalars[\"DateTime\"][\"output\"]>;\n readonly createdAt: Scalars[\"DateTime\"][\"output\"];\n readonly error?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly id: Scalars[\"String\"][\"output\"];\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 readonly result?: Maybe<Scalars[\"JSONObject\"][\"output\"]>;\n readonly status: Scalars[\"String\"][\"output\"];\n};\n\nexport type MoveRelationshipResult = {\n readonly source: PhDocument;\n readonly target: PhDocument;\n};\n\nexport type Mutation = {\n readonly addRelationship: PhDocument;\n readonly createDocument: PhDocument;\n readonly createEmptyDocument: PhDocument;\n readonly deleteDocument: Scalars[\"Boolean\"][\"output\"];\n readonly deleteDocuments: Scalars[\"Boolean\"][\"output\"];\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 readonly execute: PhDocument;\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 readonly executeAsync: JobInfo;\n readonly moveRelationship: MoveRelationshipResult;\n /** @deprecated 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 readonly mutateDocument: PhDocument;\n /** @deprecated Use executeAsync, which is typed and returns the job rather than only its id. */\n readonly mutateDocumentAsync: Scalars[\"String\"][\"output\"];\n readonly pushSyncEnvelopes: Scalars[\"Boolean\"][\"output\"];\n readonly removeRelationship: PhDocument;\n readonly renameDocument: PhDocument;\n readonly setPreferredEditor: PhDocument;\n readonly touchChannel: TouchChannelResult;\n readonly updateRelationship: PhDocument;\n};\n\nexport type MutationAddRelationshipArgs = {\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n metadata?: InputMaybe<Scalars[\"JSONObject\"][\"input\"]>;\n relationshipType: Scalars[\"String\"][\"input\"];\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n};\n\nexport type MutationCreateDocumentArgs = {\n document: Scalars[\"JSONObject\"][\"input\"];\n parentIdentifier?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n};\n\nexport type MutationCreateEmptyDocumentArgs = {\n documentType: Scalars[\"String\"][\"input\"];\n parentIdentifier?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n};\n\nexport type MutationDeleteDocumentArgs = {\n identifier: Scalars[\"String\"][\"input\"];\n propagate?: InputMaybe<PropagationMode>;\n};\n\nexport type MutationDeleteDocumentsArgs = {\n identifiers: ReadonlyArray<Scalars[\"String\"][\"input\"]>;\n propagate?: InputMaybe<PropagationMode>;\n};\n\nexport type MutationExecuteArgs = {\n actions: ReadonlyArray<ActionInput>;\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n documentIdentifier: Scalars[\"String\"][\"input\"];\n};\n\nexport type MutationExecuteAsyncArgs = {\n actions: ReadonlyArray<ActionInput>;\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n documentIdentifier: Scalars[\"String\"][\"input\"];\n};\n\nexport type MutationMoveRelationshipArgs = {\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n relationshipType: Scalars[\"String\"][\"input\"];\n sourceParentIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n targetParentIdentifier: Scalars[\"String\"][\"input\"];\n};\n\nexport type MutationMutateDocumentArgs = {\n actions: ReadonlyArray<Scalars[\"JSONObject\"][\"input\"]>;\n documentIdentifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type MutationMutateDocumentAsyncArgs = {\n actions: ReadonlyArray<Scalars[\"JSONObject\"][\"input\"]>;\n documentIdentifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type MutationPushSyncEnvelopesArgs = {\n envelopes: ReadonlyArray<SyncEnvelopeInput>;\n};\n\nexport type MutationRemoveRelationshipArgs = {\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n relationshipType: Scalars[\"String\"][\"input\"];\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n};\n\nexport type MutationRenameDocumentArgs = {\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n documentIdentifier: Scalars[\"String\"][\"input\"];\n name: Scalars[\"String\"][\"input\"];\n};\n\nexport type MutationSetPreferredEditorArgs = {\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n documentIdentifier: Scalars[\"String\"][\"input\"];\n preferredEditor?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n};\n\nexport type MutationTouchChannelArgs = {\n input: TouchChannelInput;\n};\n\nexport type MutationUpdateRelationshipArgs = {\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n metadata?: InputMaybe<Scalars[\"JSONObject\"][\"input\"]>;\n relationshipType: Scalars[\"String\"][\"input\"];\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n};\n\nexport type OperationContext = {\n readonly branch: Scalars[\"String\"][\"output\"];\n readonly documentId: Scalars[\"String\"][\"output\"];\n readonly documentType: Scalars[\"String\"][\"output\"];\n readonly ordinal: Scalars[\"Int\"][\"output\"];\n readonly scope: Scalars[\"String\"][\"output\"];\n};\n\nexport type OperationContextInput = {\n readonly branch: Scalars[\"String\"][\"input\"];\n readonly documentId: Scalars[\"String\"][\"input\"];\n readonly documentType: Scalars[\"String\"][\"input\"];\n readonly ordinal: Scalars[\"Int\"][\"input\"];\n readonly scope: Scalars[\"String\"][\"input\"];\n};\n\nexport type OperationInput = {\n readonly action: ActionInput;\n readonly deniedReason?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly error?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly hash: Scalars[\"String\"][\"input\"];\n readonly id?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly index: Scalars[\"Int\"][\"input\"];\n readonly skip: Scalars[\"Int\"][\"input\"];\n readonly timestampUtcMs: Scalars[\"String\"][\"input\"];\n};\n\nexport type OperationWithContext = {\n readonly context: OperationContext;\n readonly operation: ReactorOperation;\n};\n\nexport type OperationWithContextInput = {\n readonly context: OperationContextInput;\n readonly operation: OperationInput;\n};\n\nexport type OperationsFilterInput = {\n readonly actionTypes?: InputMaybe<ReadonlyArray<Scalars[\"String\"][\"input\"]>>;\n readonly branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly documentId: Scalars[\"String\"][\"input\"];\n readonly scopes?: InputMaybe<ReadonlyArray<Scalars[\"String\"][\"input\"]>>;\n readonly sinceRevision?: InputMaybe<Scalars[\"Int\"][\"input\"]>;\n readonly timestampFrom?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly timestampTo?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n};\n\nexport type PhDocument = {\n readonly createdAtUtcIso: Scalars[\"DateTime\"][\"output\"];\n readonly documentType: Scalars[\"String\"][\"output\"];\n readonly id: Scalars[\"String\"][\"output\"];\n readonly lastModifiedAtUtcIso: Scalars[\"DateTime\"][\"output\"];\n readonly name: Scalars[\"String\"][\"output\"];\n readonly operations?: Maybe<ReactorOperationResultPage>;\n readonly preferredEditor?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly revisionsList: ReadonlyArray<Revision>;\n readonly slug?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly state: Scalars[\"JSONObject\"][\"output\"];\n};\n\nexport type PhDocumentOperationsArgs = {\n filter?: InputMaybe<DocumentOperationsFilterInput>;\n paging?: InputMaybe<PagingInput>;\n};\n\nexport type PhDocumentResultPage = {\n readonly cursor?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly hasNextPage: Scalars[\"Boolean\"][\"output\"];\n readonly hasPreviousPage: Scalars[\"Boolean\"][\"output\"];\n readonly items: ReadonlyArray<PhDocument>;\n};\n\nexport type PagingInput = {\n readonly cursor?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly limit?: InputMaybe<Scalars[\"Int\"][\"input\"]>;\n readonly offset?: InputMaybe<Scalars[\"Int\"][\"input\"]>;\n};\n\nexport type PollSyncEnvelopesResult = {\n readonly ackOrdinal: Scalars[\"Int\"][\"output\"];\n readonly deadLetters: ReadonlyArray<DeadLetterInfo>;\n readonly envelopes: ReadonlyArray<SyncEnvelope>;\n readonly hasMore: Scalars[\"Boolean\"][\"output\"];\n};\n\nexport enum PropagationMode {\n Cascade = \"CASCADE\",\n Orphan = \"ORPHAN\",\n}\n\nexport type Query = {\n readonly document?: Maybe<DocumentWithChildren>;\n readonly documentIncomingRelationshipEdges: DocumentRelationshipResultPage;\n readonly documentIncomingRelationships: PhDocumentResultPage;\n readonly documentModels: DocumentModelResultPage;\n readonly documentOperations: ReactorOperationResultPage;\n readonly documentOutgoingRelationshipEdges: DocumentRelationshipResultPage;\n readonly documentOutgoingRelationships: PhDocumentResultPage;\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 readonly evaluateActions: ActionEvaluations;\n readonly findDocuments: PhDocumentResultPage;\n readonly jobStatus?: Maybe<JobInfo>;\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 readonly pollSyncEnvelopes: PollSyncEnvelopesResult;\n};\n\nexport type QueryDocumentArgs = {\n identifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type QueryDocumentIncomingRelationshipEdgesArgs = {\n paging?: InputMaybe<PagingInput>;\n relationshipType?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n targetIdentifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type QueryDocumentIncomingRelationshipsArgs = {\n paging?: InputMaybe<PagingInput>;\n relationshipType: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type QueryDocumentModelsArgs = {\n namespace?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n paging?: InputMaybe<PagingInput>;\n};\n\nexport type QueryDocumentOperationsArgs = {\n filter: OperationsFilterInput;\n paging?: InputMaybe<PagingInput>;\n};\n\nexport type QueryDocumentOutgoingRelationshipEdgesArgs = {\n paging?: InputMaybe<PagingInput>;\n relationshipType?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type QueryDocumentOutgoingRelationshipsArgs = {\n paging?: InputMaybe<PagingInput>;\n relationshipType: Scalars[\"String\"][\"input\"];\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type QueryEvaluateActionsArgs = {\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n candidates: ReadonlyArray<ActionCandidateInput>;\n documentIdentifier: Scalars[\"String\"][\"input\"];\n};\n\nexport type QueryFindDocumentsArgs = {\n paging?: InputMaybe<PagingInput>;\n search?: InputMaybe<SearchFilterInput>;\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type QueryJobStatusArgs = {\n jobId: Scalars[\"String\"][\"input\"];\n};\n\nexport type QueryPollSyncEnvelopesArgs = {\n channelId: Scalars[\"String\"][\"input\"];\n outboxAck: Scalars[\"Int\"][\"input\"];\n outboxLatest: Scalars[\"Int\"][\"input\"];\n};\n\nexport type ReactorOperation = {\n readonly action: Action;\n readonly deniedReason?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly error?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly hash: Scalars[\"String\"][\"output\"];\n readonly id?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly index: Scalars[\"Int\"][\"output\"];\n readonly skip: Scalars[\"Int\"][\"output\"];\n readonly timestampUtcMs: Scalars[\"String\"][\"output\"];\n};\n\nexport type ReactorOperationResultPage = {\n readonly cursor?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly hasNextPage: Scalars[\"Boolean\"][\"output\"];\n readonly hasPreviousPage: Scalars[\"Boolean\"][\"output\"];\n readonly items: ReadonlyArray<ReactorOperation>;\n};\n\nexport type ReactorSigner = {\n readonly app?: Maybe<ReactorSignerApp>;\n readonly signatures: ReadonlyArray<Scalars[\"String\"][\"output\"]>;\n readonly user?: Maybe<ReactorSignerUser>;\n};\n\nexport type ReactorSignerApp = {\n readonly key: Scalars[\"String\"][\"output\"];\n readonly name: Scalars[\"String\"][\"output\"];\n};\n\nexport type ReactorSignerAppInput = {\n readonly key: Scalars[\"String\"][\"input\"];\n readonly name: Scalars[\"String\"][\"input\"];\n};\n\nexport type ReactorSignerInput = {\n readonly app?: InputMaybe<ReactorSignerAppInput>;\n readonly signatures: ReadonlyArray<Scalars[\"String\"][\"input\"]>;\n readonly user?: InputMaybe<ReactorSignerUserInput>;\n};\n\nexport type ReactorSignerUser = {\n readonly address: Scalars[\"String\"][\"output\"];\n readonly chainId: Scalars[\"Int\"][\"output\"];\n readonly networkId: Scalars[\"String\"][\"output\"];\n};\n\nexport type ReactorSignerUserInput = {\n readonly address: Scalars[\"String\"][\"input\"];\n readonly chainId: Scalars[\"Int\"][\"input\"];\n readonly networkId: Scalars[\"String\"][\"input\"];\n};\n\nexport type RemoteCursor = {\n readonly cursorOrdinal: Scalars[\"Int\"][\"output\"];\n readonly lastSyncedAtUtcMs?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly remoteName: Scalars[\"String\"][\"output\"];\n};\n\nexport type RemoteCursorInput = {\n readonly cursorOrdinal: Scalars[\"Int\"][\"input\"];\n readonly lastSyncedAtUtcMs?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly remoteName: Scalars[\"String\"][\"input\"];\n};\n\nexport type RemoteFilterInput = {\n readonly branch: Scalars[\"String\"][\"input\"];\n readonly documentId: ReadonlyArray<Scalars[\"String\"][\"input\"]>;\n readonly scope: ReadonlyArray<Scalars[\"String\"][\"input\"]>;\n};\n\nexport type Revision = {\n readonly revision: Scalars[\"Int\"][\"output\"];\n readonly scope: Scalars[\"String\"][\"output\"];\n};\n\nexport type SearchFilterInput = {\n readonly identifiers?: InputMaybe<ReadonlyArray<Scalars[\"String\"][\"input\"]>>;\n readonly parentId?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly type?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n};\n\nexport type Subscription = {\n readonly documentChanges: DocumentChangeEvent;\n readonly jobChanges: JobChangeEvent;\n};\n\nexport type SubscriptionDocumentChangesArgs = {\n search?: InputMaybe<SearchFilterInput>;\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type SubscriptionJobChangesArgs = {\n jobId: Scalars[\"String\"][\"input\"];\n};\n\nexport type SyncEnvelope = {\n readonly channelMeta: ChannelMeta;\n readonly cursor?: Maybe<RemoteCursor>;\n readonly dependsOn?: Maybe<ReadonlyArray<Scalars[\"String\"][\"output\"]>>;\n readonly key?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly operations?: Maybe<ReadonlyArray<OperationWithContext>>;\n readonly type: SyncEnvelopeType;\n};\n\nexport type SyncEnvelopeInput = {\n readonly channelMeta: ChannelMetaInput;\n readonly cursor?: InputMaybe<RemoteCursorInput>;\n readonly dependsOn?: InputMaybe<ReadonlyArray<Scalars[\"String\"][\"input\"]>>;\n readonly key?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly operations?: InputMaybe<ReadonlyArray<OperationWithContextInput>>;\n readonly type: SyncEnvelopeType;\n};\n\nexport enum SyncEnvelopeType {\n Ack = \"ACK\",\n Operations = \"OPERATIONS\",\n}\n\nexport type TouchChannelInput = {\n readonly collectionId: Scalars[\"String\"][\"input\"];\n readonly filter: RemoteFilterInput;\n readonly id: Scalars[\"String\"][\"input\"];\n readonly name: Scalars[\"String\"][\"input\"];\n readonly sinceTimestampUtcMs: Scalars[\"String\"][\"input\"];\n};\n\nexport type TouchChannelResult = {\n readonly ackOrdinal: Scalars[\"Int\"][\"output\"];\n readonly success: Scalars[\"Boolean\"][\"output\"];\n};\n\nexport type ViewFilterInput = {\n readonly branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly scopes?: InputMaybe<ReadonlyArray<Scalars[\"String\"][\"input\"]>>;\n};\n\nexport type PhDocumentFieldsFragment = {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n};\n\nexport type DocumentRelationshipFieldsFragment = {\n readonly sourceId: string;\n readonly targetId: string;\n readonly relationshipType: string;\n readonly metadata?: NonNullable<unknown> | null | undefined;\n readonly createdAt: string | Date;\n readonly updatedAt: string | Date;\n};\n\nexport type GetDocumentModelsQueryVariables = Exact<{\n namespace?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n paging?: InputMaybe<PagingInput>;\n}>;\n\nexport type GetDocumentModelsQuery = {\n readonly documentModels: {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly id: string;\n readonly name: string;\n readonly namespace?: string | null | undefined;\n readonly version?: string | null | undefined;\n readonly specification: NonNullable<unknown>;\n }>;\n };\n};\n\nexport type GetDocumentQueryVariables = Exact<{\n identifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n}>;\n\nexport type GetDocumentQuery = {\n readonly document?:\n | {\n readonly childIds: ReadonlyArray<string>;\n readonly document: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n }\n | null\n | undefined;\n};\n\nexport type GetDocumentWithOperationsQueryVariables = Exact<{\n identifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n operationsFilter?: InputMaybe<DocumentOperationsFilterInput>;\n operationsPaging?: InputMaybe<PagingInput>;\n}>;\n\nexport type GetDocumentWithOperationsQuery = {\n readonly document?:\n | {\n readonly childIds: ReadonlyArray<string>;\n readonly document: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly operations?:\n | {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly index: number;\n readonly timestampUtcMs: string;\n readonly hash: string;\n readonly skip: number;\n readonly error?: string | null | undefined;\n readonly deniedReason?: string | null | undefined;\n readonly id?: string | null | undefined;\n readonly action: {\n readonly id: string;\n readonly type: string;\n readonly timestampUtcMs: string;\n readonly input: NonNullable<unknown>;\n readonly scope: string;\n readonly context?:\n | {\n readonly signer?:\n | {\n readonly signatures: ReadonlyArray<string>;\n readonly user?:\n | {\n readonly address: string;\n readonly networkId: string;\n readonly chainId: number;\n }\n | null\n | undefined;\n readonly app?:\n | {\n readonly name: string;\n readonly key: string;\n }\n | null\n | undefined;\n }\n | null\n | undefined;\n }\n | null\n | undefined;\n };\n }>;\n }\n | null\n | undefined;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n }\n | null\n | undefined;\n};\n\nexport type GetDocumentOutgoingRelationshipsQueryVariables = Exact<{\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n paging?: InputMaybe<PagingInput>;\n}>;\n\nexport type GetDocumentOutgoingRelationshipsQuery = {\n readonly documentOutgoingRelationships: {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n }>;\n };\n};\n\nexport type GetDocumentIncomingRelationshipsQueryVariables = Exact<{\n targetIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n paging?: InputMaybe<PagingInput>;\n}>;\n\nexport type GetDocumentIncomingRelationshipsQuery = {\n readonly documentIncomingRelationships: {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n }>;\n };\n};\n\nexport type GetDocumentOutgoingRelationshipEdgesQueryVariables = Exact<{\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n view?: InputMaybe<ViewFilterInput>;\n paging?: InputMaybe<PagingInput>;\n}>;\n\nexport type GetDocumentOutgoingRelationshipEdgesQuery = {\n readonly documentOutgoingRelationshipEdges: {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly sourceId: string;\n readonly targetId: string;\n readonly relationshipType: string;\n readonly metadata?: NonNullable<unknown> | null | undefined;\n readonly createdAt: string | Date;\n readonly updatedAt: string | Date;\n }>;\n };\n};\n\nexport type GetDocumentIncomingRelationshipEdgesQueryVariables = Exact<{\n targetIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n view?: InputMaybe<ViewFilterInput>;\n paging?: InputMaybe<PagingInput>;\n}>;\n\nexport type GetDocumentIncomingRelationshipEdgesQuery = {\n readonly documentIncomingRelationshipEdges: {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly sourceId: string;\n readonly targetId: string;\n readonly relationshipType: string;\n readonly metadata?: NonNullable<unknown> | null | undefined;\n readonly createdAt: string | Date;\n readonly updatedAt: string | Date;\n }>;\n };\n};\n\nexport type FindDocumentsQueryVariables = Exact<{\n search?: InputMaybe<SearchFilterInput>;\n view?: InputMaybe<ViewFilterInput>;\n paging?: InputMaybe<PagingInput>;\n}>;\n\nexport type FindDocumentsQuery = {\n readonly findDocuments: {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n }>;\n };\n};\n\nexport type GetDocumentOperationsQueryVariables = Exact<{\n filter: OperationsFilterInput;\n paging?: InputMaybe<PagingInput>;\n}>;\n\nexport type GetDocumentOperationsQuery = {\n readonly documentOperations: {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly index: number;\n readonly timestampUtcMs: string;\n readonly hash: string;\n readonly skip: number;\n readonly error?: string | null | undefined;\n readonly deniedReason?: string | null | undefined;\n readonly id?: string | null | undefined;\n readonly action: {\n readonly id: string;\n readonly type: string;\n readonly timestampUtcMs: string;\n readonly input: NonNullable<unknown>;\n readonly scope: string;\n readonly context?:\n | {\n readonly signer?:\n | {\n readonly signatures: ReadonlyArray<string>;\n readonly user?:\n | {\n readonly address: string;\n readonly networkId: string;\n readonly chainId: number;\n }\n | null\n | undefined;\n readonly app?:\n | { readonly name: string; readonly key: string }\n | null\n | undefined;\n }\n | null\n | undefined;\n }\n | null\n | undefined;\n };\n }>;\n };\n};\n\nexport type GetJobStatusQueryVariables = Exact<{\n jobId: Scalars[\"String\"][\"input\"];\n}>;\n\nexport type GetJobStatusQuery = {\n readonly jobStatus?:\n | {\n readonly id: string;\n readonly status: string;\n readonly result?: NonNullable<unknown> | null | undefined;\n readonly error?: string | null | undefined;\n readonly createdAt: string | Date;\n readonly completedAt?: string | Date | null | undefined;\n }\n | null\n | undefined;\n};\n\nexport type EvaluateActionsQueryVariables = Exact<{\n documentIdentifier: Scalars[\"String\"][\"input\"];\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n candidates: ReadonlyArray<ActionCandidateInput>;\n}>;\n\nexport type EvaluateActionsQuery = {\n readonly evaluateActions: {\n readonly allAllowed: boolean;\n readonly anyAllowed: boolean;\n readonly allDenied: boolean;\n readonly anyDenied: boolean;\n readonly evaluations: ReadonlyArray<{\n readonly decision: AuthDecision;\n readonly reason?: string | null | undefined;\n }>;\n };\n};\n\nexport type CreateDocumentMutationVariables = Exact<{\n document: Scalars[\"JSONObject\"][\"input\"];\n parentIdentifier?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type CreateDocumentMutation = {\n readonly createDocument: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type CreateEmptyDocumentMutationVariables = Exact<{\n documentType: Scalars[\"String\"][\"input\"];\n parentIdentifier?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type CreateEmptyDocumentMutation = {\n readonly createEmptyDocument: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type MutateDocumentMutationVariables = Exact<{\n documentIdentifier: Scalars[\"String\"][\"input\"];\n actions: ReadonlyArray<ActionInput>;\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type MutateDocumentMutation = {\n readonly mutateDocument: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type MutateDocumentAsyncMutationVariables = Exact<{\n documentIdentifier: Scalars[\"String\"][\"input\"];\n actions: ReadonlyArray<ActionInput>;\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type MutateDocumentAsyncMutation = {\n readonly mutateDocumentAsync: {\n readonly id: string;\n readonly status: string;\n readonly result?: NonNullable<unknown> | null | undefined;\n readonly error?: string | null | undefined;\n readonly createdAt: string | Date;\n readonly completedAt?: string | Date | null | undefined;\n };\n};\n\nexport type RenameDocumentMutationVariables = Exact<{\n documentIdentifier: Scalars[\"String\"][\"input\"];\n name: Scalars[\"String\"][\"input\"];\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type RenameDocumentMutation = {\n readonly renameDocument: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type SetPreferredEditorMutationVariables = Exact<{\n documentIdentifier: Scalars[\"String\"][\"input\"];\n preferredEditor?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type SetPreferredEditorMutation = {\n readonly setPreferredEditor: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type AddRelationshipMutationVariables = Exact<{\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType: Scalars[\"String\"][\"input\"];\n metadata?: InputMaybe<Scalars[\"JSONObject\"][\"input\"]>;\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type AddRelationshipMutation = {\n readonly addRelationship: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type UpdateRelationshipMutationVariables = Exact<{\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType: Scalars[\"String\"][\"input\"];\n metadata?: InputMaybe<Scalars[\"JSONObject\"][\"input\"]>;\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type UpdateRelationshipMutation = {\n readonly updateRelationship: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type RemoveRelationshipMutationVariables = Exact<{\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType: Scalars[\"String\"][\"input\"];\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type RemoveRelationshipMutation = {\n readonly removeRelationship: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type MoveRelationshipMutationVariables = Exact<{\n sourceParentIdentifier: Scalars[\"String\"][\"input\"];\n targetParentIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType: Scalars[\"String\"][\"input\"];\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type MoveRelationshipMutation = {\n readonly moveRelationship: {\n readonly source: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n readonly target: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n };\n};\n\nexport type DeleteDocumentMutationVariables = Exact<{\n identifier: Scalars[\"String\"][\"input\"];\n propagate?: InputMaybe<PropagationMode>;\n}>;\n\nexport type DeleteDocumentMutation = { readonly deleteDocument: boolean };\n\nexport type DeleteDocumentsMutationVariables = Exact<{\n identifiers: ReadonlyArray<Scalars[\"String\"][\"input\"]>;\n propagate?: InputMaybe<PropagationMode>;\n}>;\n\nexport type DeleteDocumentsMutation = { readonly deleteDocuments: boolean };\n\nexport type DocumentChangesSubscriptionVariables = Exact<{\n search?: InputMaybe<SearchFilterInput>;\n view?: InputMaybe<ViewFilterInput>;\n}>;\n\nexport type DocumentChangesSubscription = {\n readonly documentChanges: {\n readonly type: DocumentChangeType;\n readonly documents: ReadonlyArray<{\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n }>;\n readonly context?:\n | {\n readonly parentId?: string | null | undefined;\n readonly childId?: string | null | undefined;\n }\n | null\n | undefined;\n };\n};\n\nexport type JobChangesSubscriptionVariables = Exact<{\n jobId: Scalars[\"String\"][\"input\"];\n}>;\n\nexport type JobChangesSubscription = {\n readonly jobChanges: {\n readonly jobId: string;\n readonly status: string;\n readonly result?: NonNullable<unknown> | null | undefined;\n readonly error?: string | null | undefined;\n };\n};\n\nexport type PollSyncEnvelopesQueryVariables = Exact<{\n channelId: Scalars[\"String\"][\"input\"];\n outboxAck: Scalars[\"Int\"][\"input\"];\n outboxLatest: Scalars[\"Int\"][\"input\"];\n}>;\n\nexport type PollSyncEnvelopesQuery = {\n readonly pollSyncEnvelopes: {\n readonly ackOrdinal: number;\n readonly hasMore: boolean;\n readonly envelopes: ReadonlyArray<{\n readonly type: SyncEnvelopeType;\n readonly key?: string | null | undefined;\n readonly dependsOn?: ReadonlyArray<string> | null | undefined;\n readonly channelMeta: { readonly id: string };\n readonly operations?:\n | ReadonlyArray<{\n readonly operation: {\n readonly index: number;\n readonly timestampUtcMs: string;\n readonly hash: string;\n readonly skip: number;\n readonly error?: string | null | undefined;\n readonly deniedReason?: string | null | undefined;\n readonly id?: string | null | undefined;\n readonly action: {\n readonly id: string;\n readonly type: string;\n readonly timestampUtcMs: string;\n readonly input: NonNullable<unknown>;\n readonly scope: string;\n readonly context?:\n | {\n readonly signer?:\n | {\n readonly signatures: ReadonlyArray<string>;\n readonly user?:\n | {\n readonly address: string;\n readonly networkId: string;\n readonly chainId: number;\n }\n | null\n | undefined;\n readonly app?:\n | { readonly name: string; readonly key: string }\n | null\n | undefined;\n }\n | null\n | undefined;\n }\n | null\n | undefined;\n };\n };\n readonly context: {\n readonly documentId: string;\n readonly documentType: string;\n readonly scope: string;\n readonly branch: string;\n };\n }>\n | null\n | undefined;\n readonly cursor?:\n | {\n readonly remoteName: string;\n readonly cursorOrdinal: number;\n readonly lastSyncedAtUtcMs?: string | null | undefined;\n }\n | null\n | undefined;\n }>;\n readonly deadLetters: ReadonlyArray<{\n readonly documentId: string;\n readonly error: string;\n readonly errorType?: string | null | undefined;\n }>;\n };\n};\n\nexport type TouchChannelMutationVariables = Exact<{\n input: TouchChannelInput;\n}>;\n\nexport type TouchChannelMutation = {\n readonly touchChannel: {\n readonly success: boolean;\n readonly ackOrdinal: number;\n };\n};\n\nexport type PushSyncEnvelopesMutationVariables = Exact<{\n envelopes: ReadonlyArray<SyncEnvelopeInput>;\n}>;\n\nexport type PushSyncEnvelopesMutation = { readonly pushSyncEnvelopes: boolean };\n\nexport type WithIndex<TObject> = TObject & Record<string, any>;\nexport type ResolversObject<TObject> = WithIndex<TObject>;\n\nexport type ResolverTypeWrapper<T> = Promise<T> | T;\n\nexport type ResolverWithResolve<TResult, TParent, TContext, TArgs> = {\n resolve: ResolverFn<TResult, TParent, TContext, TArgs>;\n};\nexport type Resolver<\n TResult,\n TParent = Record<PropertyKey, never>,\n TContext = Record<PropertyKey, never>,\n TArgs = Record<PropertyKey, never>,\n> =\n | ResolverFn<TResult, TParent, TContext, TArgs>\n | ResolverWithResolve<TResult, TParent, TContext, TArgs>;\n\nexport type ResolverFn<TResult, TParent, TContext, TArgs> = (\n parent: TParent,\n args: TArgs,\n context: TContext,\n info: GraphQLResolveInfo,\n) => Promise<TResult> | TResult;\n\nexport type SubscriptionSubscribeFn<TResult, TParent, TContext, TArgs> = (\n parent: TParent,\n args: TArgs,\n context: TContext,\n info: GraphQLResolveInfo,\n) => AsyncIterable<TResult> | Promise<AsyncIterable<TResult>>;\n\nexport type SubscriptionResolveFn<TResult, TParent, TContext, TArgs> = (\n parent: TParent,\n args: TArgs,\n context: TContext,\n info: GraphQLResolveInfo,\n) => TResult | Promise<TResult>;\n\nexport interface SubscriptionSubscriberObject<\n TResult,\n TKey extends string,\n TParent,\n TContext,\n TArgs,\n> {\n subscribe: SubscriptionSubscribeFn<\n { [key in TKey]: TResult },\n TParent,\n TContext,\n TArgs\n >;\n resolve?: SubscriptionResolveFn<\n TResult,\n { [key in TKey]: TResult },\n TContext,\n TArgs\n >;\n}\n\nexport interface SubscriptionResolverObject<TResult, TParent, TContext, TArgs> {\n subscribe: SubscriptionSubscribeFn<any, TParent, TContext, TArgs>;\n resolve: SubscriptionResolveFn<TResult, any, TContext, TArgs>;\n}\n\nexport type SubscriptionObject<\n TResult,\n TKey extends string,\n TParent,\n TContext,\n TArgs,\n> =\n | SubscriptionSubscriberObject<TResult, TKey, TParent, TContext, TArgs>\n | SubscriptionResolverObject<TResult, TParent, TContext, TArgs>;\n\nexport type SubscriptionResolver<\n TResult,\n TKey extends string,\n TParent = Record<PropertyKey, never>,\n TContext = Record<PropertyKey, never>,\n TArgs = Record<PropertyKey, never>,\n> =\n | ((\n ...args: any[]\n ) => SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>)\n | SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>;\n\nexport type TypeResolveFn<\n TTypes,\n TParent = Record<PropertyKey, never>,\n TContext = Record<PropertyKey, never>,\n> = (\n parent: TParent,\n context: TContext,\n info: GraphQLResolveInfo,\n) => Maybe<TTypes> | Promise<Maybe<TTypes>>;\n\nexport type IsTypeOfResolverFn<\n T = Record<PropertyKey, never>,\n TContext = Record<PropertyKey, never>,\n> = (\n obj: T,\n context: TContext,\n info: GraphQLResolveInfo,\n) => boolean | Promise<boolean>;\n\nexport type NextResolverFn<T> = () => Promise<T>;\n\nexport type DirectiveResolverFn<\n TResult = Record<PropertyKey, never>,\n TParent = Record<PropertyKey, never>,\n TContext = Record<PropertyKey, never>,\n TArgs = Record<PropertyKey, never>,\n> = (\n next: NextResolverFn<TResult>,\n parent: TParent,\n args: TArgs,\n context: TContext,\n info: GraphQLResolveInfo,\n) => TResult | Promise<TResult>;\n\n/** Mapping between all available schema types and the resolvers types */\nexport type ResolversTypes = ResolversObject<{\n Action: ResolverTypeWrapper<Action>;\n ActionCandidateInput: ActionCandidateInput;\n ActionContext: ResolverTypeWrapper<ActionContext>;\n ActionContextInput: ActionContextInput;\n ActionEvaluation: ResolverTypeWrapper<ActionEvaluation>;\n ActionEvaluations: ResolverTypeWrapper<ActionEvaluations>;\n ActionInput: ActionInput;\n AuthDecision: AuthDecision;\n Boolean: ResolverTypeWrapper<Scalars[\"Boolean\"][\"output\"]>;\n ChannelMeta: ResolverTypeWrapper<ChannelMeta>;\n ChannelMetaInput: ChannelMetaInput;\n DateTime: ResolverTypeWrapper<Scalars[\"DateTime\"][\"output\"]>;\n DeadLetterInfo: ResolverTypeWrapper<DeadLetterInfo>;\n DocumentChangeContext: ResolverTypeWrapper<DocumentChangeContext>;\n DocumentChangeEvent: ResolverTypeWrapper<DocumentChangeEvent>;\n DocumentChangeType: DocumentChangeType;\n DocumentModelGlobalState: ResolverTypeWrapper<DocumentModelGlobalState>;\n DocumentModelResultPage: ResolverTypeWrapper<DocumentModelResultPage>;\n DocumentOperationsFilterInput: DocumentOperationsFilterInput;\n DocumentRelationship: ResolverTypeWrapper<DocumentRelationship>;\n DocumentRelationshipResultPage: ResolverTypeWrapper<DocumentRelationshipResultPage>;\n DocumentWithChildren: ResolverTypeWrapper<DocumentWithChildren>;\n Int: ResolverTypeWrapper<Scalars[\"Int\"][\"output\"]>;\n JSONObject: ResolverTypeWrapper<Scalars[\"JSONObject\"][\"output\"]>;\n JobChangeEvent: ResolverTypeWrapper<JobChangeEvent>;\n JobInfo: ResolverTypeWrapper<JobInfo>;\n MoveRelationshipResult: ResolverTypeWrapper<MoveRelationshipResult>;\n Mutation: ResolverTypeWrapper<Record<PropertyKey, never>>;\n OperationContext: ResolverTypeWrapper<OperationContext>;\n OperationContextInput: OperationContextInput;\n OperationInput: OperationInput;\n OperationWithContext: ResolverTypeWrapper<OperationWithContext>;\n OperationWithContextInput: OperationWithContextInput;\n OperationsFilterInput: OperationsFilterInput;\n PHDocument: ResolverTypeWrapper<PhDocument>;\n PHDocumentResultPage: ResolverTypeWrapper<PhDocumentResultPage>;\n PagingInput: PagingInput;\n PollSyncEnvelopesResult: ResolverTypeWrapper<PollSyncEnvelopesResult>;\n PropagationMode: PropagationMode;\n Query: ResolverTypeWrapper<Record<PropertyKey, never>>;\n ReactorOperation: ResolverTypeWrapper<ReactorOperation>;\n ReactorOperationResultPage: ResolverTypeWrapper<ReactorOperationResultPage>;\n ReactorSigner: ResolverTypeWrapper<ReactorSigner>;\n ReactorSignerApp: ResolverTypeWrapper<ReactorSignerApp>;\n ReactorSignerAppInput: ReactorSignerAppInput;\n ReactorSignerInput: ReactorSignerInput;\n ReactorSignerUser: ResolverTypeWrapper<ReactorSignerUser>;\n ReactorSignerUserInput: ReactorSignerUserInput;\n RemoteCursor: ResolverTypeWrapper<RemoteCursor>;\n RemoteCursorInput: RemoteCursorInput;\n RemoteFilterInput: RemoteFilterInput;\n Revision: ResolverTypeWrapper<Revision>;\n SearchFilterInput: SearchFilterInput;\n String: ResolverTypeWrapper<Scalars[\"String\"][\"output\"]>;\n Subscription: ResolverTypeWrapper<Record<PropertyKey, never>>;\n SyncEnvelope: ResolverTypeWrapper<SyncEnvelope>;\n SyncEnvelopeInput: SyncEnvelopeInput;\n SyncEnvelopeType: SyncEnvelopeType;\n TouchChannelInput: TouchChannelInput;\n TouchChannelResult: ResolverTypeWrapper<TouchChannelResult>;\n ViewFilterInput: ViewFilterInput;\n}>;\n\n/** Mapping between all available schema types and the resolvers parents */\nexport type ResolversParentTypes = ResolversObject<{\n Action: Action;\n ActionCandidateInput: ActionCandidateInput;\n ActionContext: ActionContext;\n ActionContextInput: ActionContextInput;\n ActionEvaluation: ActionEvaluation;\n ActionEvaluations: ActionEvaluations;\n ActionInput: ActionInput;\n Boolean: Scalars[\"Boolean\"][\"output\"];\n ChannelMeta: ChannelMeta;\n ChannelMetaInput: ChannelMetaInput;\n DateTime: Scalars[\"DateTime\"][\"output\"];\n DeadLetterInfo: DeadLetterInfo;\n DocumentChangeContext: DocumentChangeContext;\n DocumentChangeEvent: DocumentChangeEvent;\n DocumentModelGlobalState: DocumentModelGlobalState;\n DocumentModelResultPage: DocumentModelResultPage;\n DocumentOperationsFilterInput: DocumentOperationsFilterInput;\n DocumentRelationship: DocumentRelationship;\n DocumentRelationshipResultPage: DocumentRelationshipResultPage;\n DocumentWithChildren: DocumentWithChildren;\n Int: Scalars[\"Int\"][\"output\"];\n JSONObject: Scalars[\"JSONObject\"][\"output\"];\n JobChangeEvent: JobChangeEvent;\n JobInfo: JobInfo;\n MoveRelationshipResult: MoveRelationshipResult;\n Mutation: Record<PropertyKey, never>;\n OperationContext: OperationContext;\n OperationContextInput: OperationContextInput;\n OperationInput: OperationInput;\n OperationWithContext: OperationWithContext;\n OperationWithContextInput: OperationWithContextInput;\n OperationsFilterInput: OperationsFilterInput;\n PHDocument: PhDocument;\n PHDocumentResultPage: PhDocumentResultPage;\n PagingInput: PagingInput;\n PollSyncEnvelopesResult: PollSyncEnvelopesResult;\n Query: Record<PropertyKey, never>;\n ReactorOperation: ReactorOperation;\n ReactorOperationResultPage: ReactorOperationResultPage;\n ReactorSigner: ReactorSigner;\n ReactorSignerApp: ReactorSignerApp;\n ReactorSignerAppInput: ReactorSignerAppInput;\n ReactorSignerInput: ReactorSignerInput;\n ReactorSignerUser: ReactorSignerUser;\n ReactorSignerUserInput: ReactorSignerUserInput;\n RemoteCursor: RemoteCursor;\n RemoteCursorInput: RemoteCursorInput;\n RemoteFilterInput: RemoteFilterInput;\n Revision: Revision;\n SearchFilterInput: SearchFilterInput;\n String: Scalars[\"String\"][\"output\"];\n Subscription: Record<PropertyKey, never>;\n SyncEnvelope: SyncEnvelope;\n SyncEnvelopeInput: SyncEnvelopeInput;\n TouchChannelInput: TouchChannelInput;\n TouchChannelResult: TouchChannelResult;\n ViewFilterInput: ViewFilterInput;\n}>;\n\nexport type ActionResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"Action\"] =\n ResolversParentTypes[\"Action\"],\n> = ResolversObject<{\n context?: Resolver<\n Maybe<ResolversTypes[\"ActionContext\"]>,\n ParentType,\n ContextType\n >;\n id?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n input?: Resolver<ResolversTypes[\"JSONObject\"], ParentType, ContextType>;\n scope?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n timestampUtcMs?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n type?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type ActionContextResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ActionContext\"] =\n ResolversParentTypes[\"ActionContext\"],\n> = ResolversObject<{\n signer?: Resolver<\n Maybe<ResolversTypes[\"ReactorSigner\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type ActionEvaluationResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ActionEvaluation\"] =\n ResolversParentTypes[\"ActionEvaluation\"],\n> = ResolversObject<{\n decision?: Resolver<ResolversTypes[\"AuthDecision\"], ParentType, ContextType>;\n reason?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n}>;\n\nexport type ActionEvaluationsResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ActionEvaluations\"] =\n ResolversParentTypes[\"ActionEvaluations\"],\n> = ResolversObject<{\n allAllowed?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n allDenied?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n anyAllowed?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n anyDenied?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n evaluations?: Resolver<\n ReadonlyArray<ResolversTypes[\"ActionEvaluation\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type ChannelMetaResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ChannelMeta\"] =\n ResolversParentTypes[\"ChannelMeta\"],\n> = ResolversObject<{\n id?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport interface DateTimeScalarConfig extends GraphQLScalarTypeConfig<\n ResolversTypes[\"DateTime\"],\n any\n> {\n name: \"DateTime\";\n}\n\nexport type DeadLetterInfoResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DeadLetterInfo\"] =\n ResolversParentTypes[\"DeadLetterInfo\"],\n> = ResolversObject<{\n branch?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n documentId?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n error?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n errorType?: Resolver<\n Maybe<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n jobId?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n operationCount?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n scopes?: Resolver<\n ReadonlyArray<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type DocumentChangeContextResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DocumentChangeContext\"] =\n ResolversParentTypes[\"DocumentChangeContext\"],\n> = ResolversObject<{\n childId?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n parentId?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n}>;\n\nexport type DocumentChangeEventResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DocumentChangeEvent\"] =\n ResolversParentTypes[\"DocumentChangeEvent\"],\n> = ResolversObject<{\n context?: Resolver<\n Maybe<ResolversTypes[\"DocumentChangeContext\"]>,\n ParentType,\n ContextType\n >;\n documents?: Resolver<\n ReadonlyArray<ResolversTypes[\"PHDocument\"]>,\n ParentType,\n ContextType\n >;\n type?: Resolver<\n ResolversTypes[\"DocumentChangeType\"],\n ParentType,\n ContextType\n >;\n}>;\n\nexport type DocumentModelGlobalStateResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DocumentModelGlobalState\"] =\n ResolversParentTypes[\"DocumentModelGlobalState\"],\n> = ResolversObject<{\n id?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n name?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n namespace?: Resolver<\n Maybe<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n specification?: Resolver<\n ResolversTypes[\"JSONObject\"],\n ParentType,\n ContextType\n >;\n version?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n}>;\n\nexport type DocumentModelResultPageResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DocumentModelResultPage\"] =\n ResolversParentTypes[\"DocumentModelResultPage\"],\n> = ResolversObject<{\n cursor?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n hasNextPage?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n hasPreviousPage?: Resolver<\n ResolversTypes[\"Boolean\"],\n ParentType,\n ContextType\n >;\n items?: Resolver<\n ReadonlyArray<ResolversTypes[\"DocumentModelGlobalState\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type DocumentRelationshipResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DocumentRelationship\"] =\n ResolversParentTypes[\"DocumentRelationship\"],\n> = ResolversObject<{\n createdAt?: Resolver<ResolversTypes[\"DateTime\"], ParentType, ContextType>;\n metadata?: Resolver<\n Maybe<ResolversTypes[\"JSONObject\"]>,\n ParentType,\n ContextType\n >;\n relationshipType?: Resolver<\n ResolversTypes[\"String\"],\n ParentType,\n ContextType\n >;\n sourceId?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n targetId?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n updatedAt?: Resolver<ResolversTypes[\"DateTime\"], ParentType, ContextType>;\n}>;\n\nexport type DocumentRelationshipResultPageResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DocumentRelationshipResultPage\"] =\n ResolversParentTypes[\"DocumentRelationshipResultPage\"],\n> = ResolversObject<{\n cursor?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n hasNextPage?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n hasPreviousPage?: Resolver<\n ResolversTypes[\"Boolean\"],\n ParentType,\n ContextType\n >;\n items?: Resolver<\n ReadonlyArray<ResolversTypes[\"DocumentRelationship\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type DocumentWithChildrenResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DocumentWithChildren\"] =\n ResolversParentTypes[\"DocumentWithChildren\"],\n> = ResolversObject<{\n childIds?: Resolver<\n ReadonlyArray<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n document?: Resolver<ResolversTypes[\"PHDocument\"], ParentType, ContextType>;\n}>;\n\nexport interface JsonObjectScalarConfig extends GraphQLScalarTypeConfig<\n ResolversTypes[\"JSONObject\"],\n any\n> {\n name: \"JSONObject\";\n}\n\nexport type JobChangeEventResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"JobChangeEvent\"] =\n ResolversParentTypes[\"JobChangeEvent\"],\n> = ResolversObject<{\n error?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n jobId?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n result?: Resolver<\n Maybe<ResolversTypes[\"JSONObject\"]>,\n ParentType,\n ContextType\n >;\n status?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type JobInfoResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"JobInfo\"] =\n ResolversParentTypes[\"JobInfo\"],\n> = ResolversObject<{\n completedAt?: Resolver<\n Maybe<ResolversTypes[\"DateTime\"]>,\n ParentType,\n ContextType\n >;\n createdAt?: Resolver<ResolversTypes[\"DateTime\"], ParentType, ContextType>;\n error?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n id?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n result?: Resolver<\n Maybe<ResolversTypes[\"JSONObject\"]>,\n ParentType,\n ContextType\n >;\n status?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type MoveRelationshipResultResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"MoveRelationshipResult\"] =\n ResolversParentTypes[\"MoveRelationshipResult\"],\n> = ResolversObject<{\n source?: Resolver<ResolversTypes[\"PHDocument\"], ParentType, ContextType>;\n target?: Resolver<ResolversTypes[\"PHDocument\"], ParentType, ContextType>;\n}>;\n\nexport type MutationResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"Mutation\"] =\n ResolversParentTypes[\"Mutation\"],\n> = ResolversObject<{\n addRelationship?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<\n MutationAddRelationshipArgs,\n \"relationshipType\" | \"sourceIdentifier\" | \"targetIdentifier\"\n >\n >;\n createDocument?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<MutationCreateDocumentArgs, \"document\">\n >;\n createEmptyDocument?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<MutationCreateEmptyDocumentArgs, \"documentType\">\n >;\n deleteDocument?: Resolver<\n ResolversTypes[\"Boolean\"],\n ParentType,\n ContextType,\n RequireFields<MutationDeleteDocumentArgs, \"identifier\">\n >;\n deleteDocuments?: Resolver<\n ResolversTypes[\"Boolean\"],\n ParentType,\n ContextType,\n RequireFields<MutationDeleteDocumentsArgs, \"identifiers\">\n >;\n execute?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<MutationExecuteArgs, \"actions\" | \"documentIdentifier\">\n >;\n executeAsync?: Resolver<\n ResolversTypes[\"JobInfo\"],\n ParentType,\n ContextType,\n RequireFields<MutationExecuteAsyncArgs, \"actions\" | \"documentIdentifier\">\n >;\n moveRelationship?: Resolver<\n ResolversTypes[\"MoveRelationshipResult\"],\n ParentType,\n ContextType,\n RequireFields<\n MutationMoveRelationshipArgs,\n | \"relationshipType\"\n | \"sourceParentIdentifier\"\n | \"targetIdentifier\"\n | \"targetParentIdentifier\"\n >\n >;\n mutateDocument?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<MutationMutateDocumentArgs, \"actions\" | \"documentIdentifier\">\n >;\n mutateDocumentAsync?: Resolver<\n ResolversTypes[\"String\"],\n ParentType,\n ContextType,\n RequireFields<\n MutationMutateDocumentAsyncArgs,\n \"actions\" | \"documentIdentifier\"\n >\n >;\n pushSyncEnvelopes?: Resolver<\n ResolversTypes[\"Boolean\"],\n ParentType,\n ContextType,\n RequireFields<MutationPushSyncEnvelopesArgs, \"envelopes\">\n >;\n removeRelationship?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<\n MutationRemoveRelationshipArgs,\n \"relationshipType\" | \"sourceIdentifier\" | \"targetIdentifier\"\n >\n >;\n renameDocument?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<MutationRenameDocumentArgs, \"documentIdentifier\" | \"name\">\n >;\n setPreferredEditor?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<MutationSetPreferredEditorArgs, \"documentIdentifier\">\n >;\n touchChannel?: Resolver<\n ResolversTypes[\"TouchChannelResult\"],\n ParentType,\n ContextType,\n RequireFields<MutationTouchChannelArgs, \"input\">\n >;\n updateRelationship?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<\n MutationUpdateRelationshipArgs,\n \"relationshipType\" | \"sourceIdentifier\" | \"targetIdentifier\"\n >\n >;\n}>;\n\nexport type OperationContextResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"OperationContext\"] =\n ResolversParentTypes[\"OperationContext\"],\n> = ResolversObject<{\n branch?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n documentId?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n documentType?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n ordinal?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n scope?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type OperationWithContextResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"OperationWithContext\"] =\n ResolversParentTypes[\"OperationWithContext\"],\n> = ResolversObject<{\n context?: Resolver<\n ResolversTypes[\"OperationContext\"],\n ParentType,\n ContextType\n >;\n operation?: Resolver<\n ResolversTypes[\"ReactorOperation\"],\n ParentType,\n ContextType\n >;\n}>;\n\nexport type PhDocumentResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"PHDocument\"] =\n ResolversParentTypes[\"PHDocument\"],\n> = ResolversObject<{\n createdAtUtcIso?: Resolver<\n ResolversTypes[\"DateTime\"],\n ParentType,\n ContextType\n >;\n documentType?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n id?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n lastModifiedAtUtcIso?: Resolver<\n ResolversTypes[\"DateTime\"],\n ParentType,\n ContextType\n >;\n name?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n operations?: Resolver<\n Maybe<ResolversTypes[\"ReactorOperationResultPage\"]>,\n ParentType,\n ContextType,\n Partial<PhDocumentOperationsArgs>\n >;\n preferredEditor?: Resolver<\n Maybe<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n revisionsList?: Resolver<\n ReadonlyArray<ResolversTypes[\"Revision\"]>,\n ParentType,\n ContextType\n >;\n slug?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n state?: Resolver<ResolversTypes[\"JSONObject\"], ParentType, ContextType>;\n}>;\n\nexport type PhDocumentResultPageResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"PHDocumentResultPage\"] =\n ResolversParentTypes[\"PHDocumentResultPage\"],\n> = ResolversObject<{\n cursor?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n hasNextPage?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n hasPreviousPage?: Resolver<\n ResolversTypes[\"Boolean\"],\n ParentType,\n ContextType\n >;\n items?: Resolver<\n ReadonlyArray<ResolversTypes[\"PHDocument\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type PollSyncEnvelopesResultResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"PollSyncEnvelopesResult\"] =\n ResolversParentTypes[\"PollSyncEnvelopesResult\"],\n> = ResolversObject<{\n ackOrdinal?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n deadLetters?: Resolver<\n ReadonlyArray<ResolversTypes[\"DeadLetterInfo\"]>,\n ParentType,\n ContextType\n >;\n envelopes?: Resolver<\n ReadonlyArray<ResolversTypes[\"SyncEnvelope\"]>,\n ParentType,\n ContextType\n >;\n hasMore?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n}>;\n\nexport type QueryResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"Query\"] =\n ResolversParentTypes[\"Query\"],\n> = ResolversObject<{\n document?: Resolver<\n Maybe<ResolversTypes[\"DocumentWithChildren\"]>,\n ParentType,\n ContextType,\n RequireFields<QueryDocumentArgs, \"identifier\">\n >;\n documentIncomingRelationshipEdges?: Resolver<\n ResolversTypes[\"DocumentRelationshipResultPage\"],\n ParentType,\n ContextType,\n RequireFields<\n QueryDocumentIncomingRelationshipEdgesArgs,\n \"targetIdentifier\"\n >\n >;\n documentIncomingRelationships?: Resolver<\n ResolversTypes[\"PHDocumentResultPage\"],\n ParentType,\n ContextType,\n RequireFields<\n QueryDocumentIncomingRelationshipsArgs,\n \"relationshipType\" | \"targetIdentifier\"\n >\n >;\n documentModels?: Resolver<\n ResolversTypes[\"DocumentModelResultPage\"],\n ParentType,\n ContextType,\n Partial<QueryDocumentModelsArgs>\n >;\n documentOperations?: Resolver<\n ResolversTypes[\"ReactorOperationResultPage\"],\n ParentType,\n ContextType,\n RequireFields<QueryDocumentOperationsArgs, \"filter\">\n >;\n documentOutgoingRelationshipEdges?: Resolver<\n ResolversTypes[\"DocumentRelationshipResultPage\"],\n ParentType,\n ContextType,\n RequireFields<\n QueryDocumentOutgoingRelationshipEdgesArgs,\n \"sourceIdentifier\"\n >\n >;\n documentOutgoingRelationships?: Resolver<\n ResolversTypes[\"PHDocumentResultPage\"],\n ParentType,\n ContextType,\n RequireFields<\n QueryDocumentOutgoingRelationshipsArgs,\n \"relationshipType\" | \"sourceIdentifier\"\n >\n >;\n evaluateActions?: Resolver<\n ResolversTypes[\"ActionEvaluations\"],\n ParentType,\n ContextType,\n RequireFields<QueryEvaluateActionsArgs, \"candidates\" | \"documentIdentifier\">\n >;\n findDocuments?: Resolver<\n ResolversTypes[\"PHDocumentResultPage\"],\n ParentType,\n ContextType,\n Partial<QueryFindDocumentsArgs>\n >;\n jobStatus?: Resolver<\n Maybe<ResolversTypes[\"JobInfo\"]>,\n ParentType,\n ContextType,\n RequireFields<QueryJobStatusArgs, \"jobId\">\n >;\n pollSyncEnvelopes?: Resolver<\n ResolversTypes[\"PollSyncEnvelopesResult\"],\n ParentType,\n ContextType,\n RequireFields<\n QueryPollSyncEnvelopesArgs,\n \"channelId\" | \"outboxAck\" | \"outboxLatest\"\n >\n >;\n}>;\n\nexport type ReactorOperationResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ReactorOperation\"] =\n ResolversParentTypes[\"ReactorOperation\"],\n> = ResolversObject<{\n action?: Resolver<ResolversTypes[\"Action\"], ParentType, ContextType>;\n deniedReason?: Resolver<\n Maybe<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n error?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n hash?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n id?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n index?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n skip?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n timestampUtcMs?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type ReactorOperationResultPageResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ReactorOperationResultPage\"] =\n ResolversParentTypes[\"ReactorOperationResultPage\"],\n> = ResolversObject<{\n cursor?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n hasNextPage?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n hasPreviousPage?: Resolver<\n ResolversTypes[\"Boolean\"],\n ParentType,\n ContextType\n >;\n items?: Resolver<\n ReadonlyArray<ResolversTypes[\"ReactorOperation\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type ReactorSignerResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ReactorSigner\"] =\n ResolversParentTypes[\"ReactorSigner\"],\n> = ResolversObject<{\n app?: Resolver<\n Maybe<ResolversTypes[\"ReactorSignerApp\"]>,\n ParentType,\n ContextType\n >;\n signatures?: Resolver<\n ReadonlyArray<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n user?: Resolver<\n Maybe<ResolversTypes[\"ReactorSignerUser\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type ReactorSignerAppResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ReactorSignerApp\"] =\n ResolversParentTypes[\"ReactorSignerApp\"],\n> = ResolversObject<{\n key?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n name?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type ReactorSignerUserResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ReactorSignerUser\"] =\n ResolversParentTypes[\"ReactorSignerUser\"],\n> = ResolversObject<{\n address?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n chainId?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n networkId?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type RemoteCursorResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"RemoteCursor\"] =\n ResolversParentTypes[\"RemoteCursor\"],\n> = ResolversObject<{\n cursorOrdinal?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n lastSyncedAtUtcMs?: Resolver<\n Maybe<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n remoteName?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type RevisionResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"Revision\"] =\n ResolversParentTypes[\"Revision\"],\n> = ResolversObject<{\n revision?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n scope?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type SubscriptionResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"Subscription\"] =\n ResolversParentTypes[\"Subscription\"],\n> = ResolversObject<{\n documentChanges?: SubscriptionResolver<\n ResolversTypes[\"DocumentChangeEvent\"],\n \"documentChanges\",\n ParentType,\n ContextType,\n Partial<SubscriptionDocumentChangesArgs>\n >;\n jobChanges?: SubscriptionResolver<\n ResolversTypes[\"JobChangeEvent\"],\n \"jobChanges\",\n ParentType,\n ContextType,\n RequireFields<SubscriptionJobChangesArgs, \"jobId\">\n >;\n}>;\n\nexport type SyncEnvelopeResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"SyncEnvelope\"] =\n ResolversParentTypes[\"SyncEnvelope\"],\n> = ResolversObject<{\n channelMeta?: Resolver<\n ResolversTypes[\"ChannelMeta\"],\n ParentType,\n ContextType\n >;\n cursor?: Resolver<\n Maybe<ResolversTypes[\"RemoteCursor\"]>,\n ParentType,\n ContextType\n >;\n dependsOn?: Resolver<\n Maybe<ReadonlyArray<ResolversTypes[\"String\"]>>,\n ParentType,\n ContextType\n >;\n key?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n operations?: Resolver<\n Maybe<ReadonlyArray<ResolversTypes[\"OperationWithContext\"]>>,\n ParentType,\n ContextType\n >;\n type?: Resolver<ResolversTypes[\"SyncEnvelopeType\"], ParentType, ContextType>;\n}>;\n\nexport type TouchChannelResultResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"TouchChannelResult\"] =\n ResolversParentTypes[\"TouchChannelResult\"],\n> = ResolversObject<{\n ackOrdinal?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n success?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n}>;\n\nexport type Resolvers<ContextType = Context> = ResolversObject<{\n Action?: ActionResolvers<ContextType>;\n ActionContext?: ActionContextResolvers<ContextType>;\n ActionEvaluation?: ActionEvaluationResolvers<ContextType>;\n ActionEvaluations?: ActionEvaluationsResolvers<ContextType>;\n ChannelMeta?: ChannelMetaResolvers<ContextType>;\n DateTime?: GraphQLScalarType;\n DeadLetterInfo?: DeadLetterInfoResolvers<ContextType>;\n DocumentChangeContext?: DocumentChangeContextResolvers<ContextType>;\n DocumentChangeEvent?: DocumentChangeEventResolvers<ContextType>;\n DocumentModelGlobalState?: DocumentModelGlobalStateResolvers<ContextType>;\n DocumentModelResultPage?: DocumentModelResultPageResolvers<ContextType>;\n DocumentRelationship?: DocumentRelationshipResolvers<ContextType>;\n DocumentRelationshipResultPage?: DocumentRelationshipResultPageResolvers<ContextType>;\n DocumentWithChildren?: DocumentWithChildrenResolvers<ContextType>;\n JSONObject?: GraphQLScalarType;\n JobChangeEvent?: JobChangeEventResolvers<ContextType>;\n JobInfo?: JobInfoResolvers<ContextType>;\n MoveRelationshipResult?: MoveRelationshipResultResolvers<ContextType>;\n Mutation?: MutationResolvers<ContextType>;\n OperationContext?: OperationContextResolvers<ContextType>;\n OperationWithContext?: OperationWithContextResolvers<ContextType>;\n PHDocument?: PhDocumentResolvers<ContextType>;\n PHDocumentResultPage?: PhDocumentResultPageResolvers<ContextType>;\n PollSyncEnvelopesResult?: PollSyncEnvelopesResultResolvers<ContextType>;\n Query?: QueryResolvers<ContextType>;\n ReactorOperation?: ReactorOperationResolvers<ContextType>;\n ReactorOperationResultPage?: ReactorOperationResultPageResolvers<ContextType>;\n ReactorSigner?: ReactorSignerResolvers<ContextType>;\n ReactorSignerApp?: ReactorSignerAppResolvers<ContextType>;\n ReactorSignerUser?: ReactorSignerUserResolvers<ContextType>;\n RemoteCursor?: RemoteCursorResolvers<ContextType>;\n Revision?: RevisionResolvers<ContextType>;\n Subscription?: SubscriptionResolvers<ContextType>;\n SyncEnvelope?: SyncEnvelopeResolvers<ContextType>;\n TouchChannelResult?: TouchChannelResultResolvers<ContextType>;\n}>;\n\ntype Properties<T> = Required<{\n [K in keyof T]: z.ZodType<T[K]>;\n}>;\n\ntype definedNonNullAny = {};\n\nexport const isDefinedNonNullAny = (v: any): v is definedNonNullAny =>\n v !== undefined && v !== null;\n\nexport const definedNonNullAnySchema = z\n .any()\n .refine((v) => isDefinedNonNullAny(v));\n\nexport const AuthDecisionSchema = z.enum(AuthDecision);\n\nexport const DocumentChangeTypeSchema = z.enum(DocumentChangeType);\n\nexport const PropagationModeSchema = z.enum(PropagationMode);\n\nexport const SyncEnvelopeTypeSchema = z.enum(SyncEnvelopeType);\n\nexport function ActionCandidateInputSchema(): z.ZodObject<\n Properties<ActionCandidateInput>\n> {\n return z.object({\n input: z.custom<NonNullable<unknown>>((v) => v != null).nullish(),\n scope: z.string(),\n type: z.string(),\n });\n}\n\nexport function ActionContextInputSchema(): z.ZodObject<\n Properties<ActionContextInput>\n> {\n return z.object({\n nonce: z.string().nullish(),\n prevOpHash: z.string().nullish(),\n prevOpIndex: z.number().nullish(),\n signer: z.lazy(() => ReactorSignerInputSchema().nullish()),\n });\n}\n\nexport function ActionInputSchema(): z.ZodObject<Properties<ActionInput>> {\n return z.object({\n context: z.lazy(() => ActionContextInputSchema().nullish()),\n id: z.string(),\n input: z.custom<NonNullable<unknown>>((v) => v != null),\n scope: z.string(),\n timestampUtcMs: z.string(),\n type: z.string(),\n });\n}\n\nexport function ChannelMetaInputSchema(): z.ZodObject<\n Properties<ChannelMetaInput>\n> {\n return z.object({\n id: z.string(),\n });\n}\n\nexport function DocumentOperationsFilterInputSchema(): z.ZodObject<\n Properties<DocumentOperationsFilterInput>\n> {\n return z.object({\n actionTypes: z.array(z.string()).nullish(),\n branch: z.string().nullish(),\n scopes: z.array(z.string()).nullish(),\n sinceRevision: z.number().nullish(),\n timestampFrom: z.string().nullish(),\n timestampTo: z.string().nullish(),\n });\n}\n\nexport function OperationContextInputSchema(): z.ZodObject<\n Properties<OperationContextInput>\n> {\n return z.object({\n branch: z.string(),\n documentId: z.string(),\n documentType: z.string(),\n ordinal: z.number(),\n scope: z.string(),\n });\n}\n\nexport function OperationInputSchema(): z.ZodObject<\n Properties<OperationInput>\n> {\n return z.object({\n action: z.lazy(() => ActionInputSchema()),\n deniedReason: z.string().nullish(),\n error: z.string().nullish(),\n hash: z.string(),\n id: z.string().nullish(),\n index: z.number(),\n skip: z.number(),\n timestampUtcMs: z.string(),\n });\n}\n\nexport function OperationWithContextInputSchema(): z.ZodObject<\n Properties<OperationWithContextInput>\n> {\n return z.object({\n context: z.lazy(() => OperationContextInputSchema()),\n operation: z.lazy(() => OperationInputSchema()),\n });\n}\n\nexport function OperationsFilterInputSchema(): z.ZodObject<\n Properties<OperationsFilterInput>\n> {\n return z.object({\n actionTypes: z.array(z.string()).nullish(),\n branch: z.string().nullish(),\n documentId: z.string(),\n scopes: z.array(z.string()).nullish(),\n sinceRevision: z.number().nullish(),\n timestampFrom: z.string().nullish(),\n timestampTo: z.string().nullish(),\n });\n}\n\nexport function PagingInputSchema(): z.ZodObject<Properties<PagingInput>> {\n return z.object({\n cursor: z.string().nullish(),\n limit: z.number().nullish(),\n offset: z.number().nullish(),\n });\n}\n\nexport function ReactorSignerAppInputSchema(): z.ZodObject<\n Properties<ReactorSignerAppInput>\n> {\n return z.object({\n key: z.string(),\n name: z.string(),\n });\n}\n\nexport function ReactorSignerInputSchema(): z.ZodObject<\n Properties<ReactorSignerInput>\n> {\n return z.object({\n app: z.lazy(() => ReactorSignerAppInputSchema().nullish()),\n signatures: z.array(z.string()),\n user: z.lazy(() => ReactorSignerUserInputSchema().nullish()),\n });\n}\n\nexport function ReactorSignerUserInputSchema(): z.ZodObject<\n Properties<ReactorSignerUserInput>\n> {\n return z.object({\n address: z.string(),\n chainId: z.number(),\n networkId: z.string(),\n });\n}\n\nexport function RemoteCursorInputSchema(): z.ZodObject<\n Properties<RemoteCursorInput>\n> {\n return z.object({\n cursorOrdinal: z.number(),\n lastSyncedAtUtcMs: z.string().nullish(),\n remoteName: z.string(),\n });\n}\n\nexport function RemoteFilterInputSchema(): z.ZodObject<\n Properties<RemoteFilterInput>\n> {\n return z.object({\n branch: z.string(),\n documentId: z.array(z.string()),\n scope: z.array(z.string()),\n });\n}\n\nexport function SearchFilterInputSchema(): z.ZodObject<\n Properties<SearchFilterInput>\n> {\n return z.object({\n identifiers: z.array(z.string()).nullish(),\n parentId: z.string().nullish(),\n type: z.string().nullish(),\n });\n}\n\nexport function SyncEnvelopeInputSchema(): z.ZodObject<\n Properties<SyncEnvelopeInput>\n> {\n return z.object({\n channelMeta: z.lazy(() => ChannelMetaInputSchema()),\n cursor: z.lazy(() => RemoteCursorInputSchema().nullish()),\n dependsOn: z.array(z.string()).nullish(),\n key: z.string().nullish(),\n operations: z\n .array(z.lazy(() => OperationWithContextInputSchema()))\n .nullish(),\n type: SyncEnvelopeTypeSchema,\n });\n}\n\nexport function TouchChannelInputSchema(): z.ZodObject<\n Properties<TouchChannelInput>\n> {\n return z.object({\n collectionId: z.string(),\n filter: z.lazy(() => RemoteFilterInputSchema()),\n id: z.string(),\n name: z.string(),\n sinceTimestampUtcMs: z.string(),\n });\n}\n\nexport function ViewFilterInputSchema(): z.ZodObject<\n Properties<ViewFilterInput>\n> {\n return z.object({\n branch: z.string().nullish(),\n scopes: z.array(z.string()).nullish(),\n });\n}\n\nexport const PhDocumentFieldsFragmentDoc = gql`\n fragment PHDocumentFields on PHDocument {\n id\n slug\n name\n documentType\n state\n revisionsList {\n scope\n revision\n }\n createdAtUtcIso\n lastModifiedAtUtcIso\n }\n`;\nexport const DocumentRelationshipFieldsFragmentDoc = gql`\n fragment DocumentRelationshipFields on DocumentRelationship {\n sourceId\n targetId\n relationshipType\n metadata\n createdAt\n updatedAt\n }\n`;\nexport const GetDocumentModelsDocument = gql`\n query GetDocumentModels($namespace: String, $paging: PagingInput) {\n documentModels(namespace: $namespace, paging: $paging) {\n items {\n id\n name\n namespace\n version\n specification\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n`;\nexport const GetDocumentDocument = gql`\n query GetDocument($identifier: String!, $view: ViewFilterInput) {\n document(identifier: $identifier, view: $view) {\n document {\n ...PHDocumentFields\n }\n childIds\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const GetDocumentWithOperationsDocument = gql`\n query GetDocumentWithOperations(\n $identifier: String!\n $view: ViewFilterInput\n $operationsFilter: DocumentOperationsFilterInput\n $operationsPaging: PagingInput\n ) {\n document(identifier: $identifier, view: $view) {\n document {\n ...PHDocumentFields\n operations(filter: $operationsFilter, paging: $operationsPaging) {\n items {\n index\n timestampUtcMs\n hash\n skip\n error\n deniedReason\n id\n action {\n id\n type\n timestampUtcMs\n input\n scope\n context {\n signer {\n user {\n address\n networkId\n chainId\n }\n app {\n name\n key\n }\n signatures\n }\n }\n }\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n childIds\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const GetDocumentOutgoingRelationshipsDocument = gql`\n query GetDocumentOutgoingRelationships(\n $sourceIdentifier: String!\n $relationshipType: String!\n $view: ViewFilterInput\n $paging: PagingInput\n ) {\n documentOutgoingRelationships(\n sourceIdentifier: $sourceIdentifier\n relationshipType: $relationshipType\n view: $view\n paging: $paging\n ) {\n items {\n ...PHDocumentFields\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const GetDocumentIncomingRelationshipsDocument = gql`\n query GetDocumentIncomingRelationships(\n $targetIdentifier: String!\n $relationshipType: String!\n $view: ViewFilterInput\n $paging: PagingInput\n ) {\n documentIncomingRelationships(\n targetIdentifier: $targetIdentifier\n relationshipType: $relationshipType\n view: $view\n paging: $paging\n ) {\n items {\n ...PHDocumentFields\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const GetDocumentOutgoingRelationshipEdgesDocument = gql`\n query GetDocumentOutgoingRelationshipEdges(\n $sourceIdentifier: String!\n $relationshipType: String\n $view: ViewFilterInput\n $paging: PagingInput\n ) {\n documentOutgoingRelationshipEdges(\n sourceIdentifier: $sourceIdentifier\n relationshipType: $relationshipType\n view: $view\n paging: $paging\n ) {\n items {\n ...DocumentRelationshipFields\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n ${DocumentRelationshipFieldsFragmentDoc}\n`;\nexport const GetDocumentIncomingRelationshipEdgesDocument = gql`\n query GetDocumentIncomingRelationshipEdges(\n $targetIdentifier: String!\n $relationshipType: String\n $view: ViewFilterInput\n $paging: PagingInput\n ) {\n documentIncomingRelationshipEdges(\n targetIdentifier: $targetIdentifier\n relationshipType: $relationshipType\n view: $view\n paging: $paging\n ) {\n items {\n ...DocumentRelationshipFields\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n ${DocumentRelationshipFieldsFragmentDoc}\n`;\nexport const FindDocumentsDocument = gql`\n query FindDocuments(\n $search: SearchFilterInput\n $view: ViewFilterInput\n $paging: PagingInput\n ) {\n findDocuments(search: $search, view: $view, paging: $paging) {\n items {\n ...PHDocumentFields\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const GetDocumentOperationsDocument = gql`\n query GetDocumentOperations(\n $filter: OperationsFilterInput!\n $paging: PagingInput\n ) {\n documentOperations(filter: $filter, paging: $paging) {\n items {\n index\n timestampUtcMs\n hash\n skip\n error\n deniedReason\n id\n action {\n id\n type\n timestampUtcMs\n input\n scope\n context {\n signer {\n user {\n address\n networkId\n chainId\n }\n app {\n name\n key\n }\n signatures\n }\n }\n }\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n`;\nexport const GetJobStatusDocument = gql`\n query GetJobStatus($jobId: String!) {\n jobStatus(jobId: $jobId) {\n id\n status\n result\n error\n createdAt\n completedAt\n }\n }\n`;\nexport const EvaluateActionsDocument = gql`\n query EvaluateActions(\n $documentIdentifier: String!\n $branch: String\n $candidates: [ActionCandidateInput!]!\n ) {\n evaluateActions(\n documentIdentifier: $documentIdentifier\n branch: $branch\n candidates: $candidates\n ) {\n evaluations {\n decision\n reason\n }\n allAllowed\n anyAllowed\n allDenied\n anyDenied\n }\n }\n`;\nexport const CreateDocumentDocument = gql`\n mutation CreateDocument($document: JSONObject!, $parentIdentifier: String) {\n createDocument(document: $document, parentIdentifier: $parentIdentifier) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const CreateEmptyDocumentDocument = gql`\n mutation CreateEmptyDocument(\n $documentType: String!\n $parentIdentifier: String\n ) {\n createEmptyDocument(\n documentType: $documentType\n parentIdentifier: $parentIdentifier\n ) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const MutateDocumentDocument = gql`\n mutation MutateDocument(\n $documentIdentifier: String!\n $actions: [ActionInput!]!\n $branch: String\n ) {\n mutateDocument: execute(\n documentIdentifier: $documentIdentifier\n actions: $actions\n branch: $branch\n ) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const MutateDocumentAsyncDocument = gql`\n mutation MutateDocumentAsync(\n $documentIdentifier: String!\n $actions: [ActionInput!]!\n $branch: String\n ) {\n mutateDocumentAsync: executeAsync(\n documentIdentifier: $documentIdentifier\n actions: $actions\n branch: $branch\n ) {\n id\n status\n result\n error\n createdAt\n completedAt\n }\n }\n`;\nexport const RenameDocumentDocument = gql`\n mutation RenameDocument(\n $documentIdentifier: String!\n $name: String!\n $branch: String\n ) {\n renameDocument(\n documentIdentifier: $documentIdentifier\n name: $name\n branch: $branch\n ) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const SetPreferredEditorDocument = gql`\n mutation SetPreferredEditor(\n $documentIdentifier: String!\n $preferredEditor: String\n $branch: String\n ) {\n setPreferredEditor(\n documentIdentifier: $documentIdentifier\n preferredEditor: $preferredEditor\n branch: $branch\n ) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const AddRelationshipDocument = gql`\n mutation AddRelationship(\n $sourceIdentifier: String!\n $targetIdentifier: String!\n $relationshipType: String!\n $metadata: JSONObject\n $branch: String\n ) {\n addRelationship(\n sourceIdentifier: $sourceIdentifier\n targetIdentifier: $targetIdentifier\n relationshipType: $relationshipType\n metadata: $metadata\n branch: $branch\n ) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const UpdateRelationshipDocument = gql`\n mutation UpdateRelationship(\n $sourceIdentifier: String!\n $targetIdentifier: String!\n $relationshipType: String!\n $metadata: JSONObject\n $branch: String\n ) {\n updateRelationship(\n sourceIdentifier: $sourceIdentifier\n targetIdentifier: $targetIdentifier\n relationshipType: $relationshipType\n metadata: $metadata\n branch: $branch\n ) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const RemoveRelationshipDocument = gql`\n mutation RemoveRelationship(\n $sourceIdentifier: String!\n $targetIdentifier: String!\n $relationshipType: String!\n $branch: String\n ) {\n removeRelationship(\n sourceIdentifier: $sourceIdentifier\n targetIdentifier: $targetIdentifier\n relationshipType: $relationshipType\n branch: $branch\n ) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const MoveRelationshipDocument = gql`\n mutation MoveRelationship(\n $sourceParentIdentifier: String!\n $targetParentIdentifier: String!\n $targetIdentifier: String!\n $relationshipType: String!\n $branch: String\n ) {\n moveRelationship(\n sourceParentIdentifier: $sourceParentIdentifier\n targetParentIdentifier: $targetParentIdentifier\n targetIdentifier: $targetIdentifier\n relationshipType: $relationshipType\n branch: $branch\n ) {\n source {\n ...PHDocumentFields\n }\n target {\n ...PHDocumentFields\n }\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const DeleteDocumentDocument = gql`\n mutation DeleteDocument($identifier: String!, $propagate: PropagationMode) {\n deleteDocument(identifier: $identifier, propagate: $propagate)\n }\n`;\nexport const DeleteDocumentsDocument = gql`\n mutation DeleteDocuments(\n $identifiers: [String!]!\n $propagate: PropagationMode\n ) {\n deleteDocuments(identifiers: $identifiers, propagate: $propagate)\n }\n`;\nexport const DocumentChangesDocument = gql`\n subscription DocumentChanges(\n $search: SearchFilterInput\n $view: ViewFilterInput\n ) {\n documentChanges(search: $search, view: $view) {\n type\n documents {\n ...PHDocumentFields\n }\n context {\n parentId\n childId\n }\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const JobChangesDocument = gql`\n subscription JobChanges($jobId: String!) {\n jobChanges(jobId: $jobId) {\n jobId\n status\n result\n error\n }\n }\n`;\nexport const PollSyncEnvelopesDocument = gql`\n query PollSyncEnvelopes(\n $channelId: String!\n $outboxAck: Int!\n $outboxLatest: Int!\n ) {\n pollSyncEnvelopes(\n channelId: $channelId\n outboxAck: $outboxAck\n outboxLatest: $outboxLatest\n ) {\n envelopes {\n type\n channelMeta {\n id\n }\n operations {\n operation {\n index\n timestampUtcMs\n hash\n skip\n error\n deniedReason\n id\n action {\n id\n type\n timestampUtcMs\n input\n scope\n context {\n signer {\n user {\n address\n networkId\n chainId\n }\n app {\n name\n key\n }\n signatures\n }\n }\n }\n }\n context {\n documentId\n documentType\n scope\n branch\n }\n }\n cursor {\n remoteName\n cursorOrdinal\n lastSyncedAtUtcMs\n }\n key\n dependsOn\n }\n ackOrdinal\n deadLetters {\n documentId\n error\n errorType\n }\n hasMore\n }\n }\n`;\nexport const TouchChannelDocument = gql`\n mutation TouchChannel($input: TouchChannelInput!) {\n touchChannel(input: $input) {\n success\n ackOrdinal\n }\n }\n`;\nexport const PushSyncEnvelopesDocument = gql`\n mutation PushSyncEnvelopes($envelopes: [SyncEnvelopeInput!]!) {\n pushSyncEnvelopes(envelopes: $envelopes)\n }\n`;\nexport type Requester<C = {}> = <R, V>(\n doc: DocumentNode,\n vars?: V,\n options?: C,\n) => Promise<R> | AsyncIterable<R>;\nexport function getSdk<C>(requester: Requester<C>) {\n return {\n GetDocumentModels(\n variables?: GetDocumentModelsQueryVariables,\n options?: C,\n ): Promise<GetDocumentModelsQuery> {\n return requester<GetDocumentModelsQuery, GetDocumentModelsQueryVariables>(\n GetDocumentModelsDocument,\n variables,\n options,\n ) as Promise<GetDocumentModelsQuery>;\n },\n GetDocument(\n variables: GetDocumentQueryVariables,\n options?: C,\n ): Promise<GetDocumentQuery> {\n return requester<GetDocumentQuery, GetDocumentQueryVariables>(\n GetDocumentDocument,\n variables,\n options,\n ) as Promise<GetDocumentQuery>;\n },\n GetDocumentWithOperations(\n variables: GetDocumentWithOperationsQueryVariables,\n options?: C,\n ): Promise<GetDocumentWithOperationsQuery> {\n return requester<\n GetDocumentWithOperationsQuery,\n GetDocumentWithOperationsQueryVariables\n >(\n GetDocumentWithOperationsDocument,\n variables,\n options,\n ) as Promise<GetDocumentWithOperationsQuery>;\n },\n GetDocumentOutgoingRelationships(\n variables: GetDocumentOutgoingRelationshipsQueryVariables,\n options?: C,\n ): Promise<GetDocumentOutgoingRelationshipsQuery> {\n return requester<\n GetDocumentOutgoingRelationshipsQuery,\n GetDocumentOutgoingRelationshipsQueryVariables\n >(\n GetDocumentOutgoingRelationshipsDocument,\n variables,\n options,\n ) as Promise<GetDocumentOutgoingRelationshipsQuery>;\n },\n GetDocumentIncomingRelationships(\n variables: GetDocumentIncomingRelationshipsQueryVariables,\n options?: C,\n ): Promise<GetDocumentIncomingRelationshipsQuery> {\n return requester<\n GetDocumentIncomingRelationshipsQuery,\n GetDocumentIncomingRelationshipsQueryVariables\n >(\n GetDocumentIncomingRelationshipsDocument,\n variables,\n options,\n ) as Promise<GetDocumentIncomingRelationshipsQuery>;\n },\n GetDocumentOutgoingRelationshipEdges(\n variables: GetDocumentOutgoingRelationshipEdgesQueryVariables,\n options?: C,\n ): Promise<GetDocumentOutgoingRelationshipEdgesQuery> {\n return requester<\n GetDocumentOutgoingRelationshipEdgesQuery,\n GetDocumentOutgoingRelationshipEdgesQueryVariables\n >(\n GetDocumentOutgoingRelationshipEdgesDocument,\n variables,\n options,\n ) as Promise<GetDocumentOutgoingRelationshipEdgesQuery>;\n },\n GetDocumentIncomingRelationshipEdges(\n variables: GetDocumentIncomingRelationshipEdgesQueryVariables,\n options?: C,\n ): Promise<GetDocumentIncomingRelationshipEdgesQuery> {\n return requester<\n GetDocumentIncomingRelationshipEdgesQuery,\n GetDocumentIncomingRelationshipEdgesQueryVariables\n >(\n GetDocumentIncomingRelationshipEdgesDocument,\n variables,\n options,\n ) as Promise<GetDocumentIncomingRelationshipEdgesQuery>;\n },\n FindDocuments(\n variables?: FindDocumentsQueryVariables,\n options?: C,\n ): Promise<FindDocumentsQuery> {\n return requester<FindDocumentsQuery, FindDocumentsQueryVariables>(\n FindDocumentsDocument,\n variables,\n options,\n ) as Promise<FindDocumentsQuery>;\n },\n GetDocumentOperations(\n variables: GetDocumentOperationsQueryVariables,\n options?: C,\n ): Promise<GetDocumentOperationsQuery> {\n return requester<\n GetDocumentOperationsQuery,\n GetDocumentOperationsQueryVariables\n >(\n GetDocumentOperationsDocument,\n variables,\n options,\n ) as Promise<GetDocumentOperationsQuery>;\n },\n GetJobStatus(\n variables: GetJobStatusQueryVariables,\n options?: C,\n ): Promise<GetJobStatusQuery> {\n return requester<GetJobStatusQuery, GetJobStatusQueryVariables>(\n GetJobStatusDocument,\n variables,\n options,\n ) as Promise<GetJobStatusQuery>;\n },\n EvaluateActions(\n variables: EvaluateActionsQueryVariables,\n options?: C,\n ): Promise<EvaluateActionsQuery> {\n return requester<EvaluateActionsQuery, EvaluateActionsQueryVariables>(\n EvaluateActionsDocument,\n variables,\n options,\n ) as Promise<EvaluateActionsQuery>;\n },\n CreateDocument(\n variables: CreateDocumentMutationVariables,\n options?: C,\n ): Promise<CreateDocumentMutation> {\n return requester<CreateDocumentMutation, CreateDocumentMutationVariables>(\n CreateDocumentDocument,\n variables,\n options,\n ) as Promise<CreateDocumentMutation>;\n },\n CreateEmptyDocument(\n variables: CreateEmptyDocumentMutationVariables,\n options?: C,\n ): Promise<CreateEmptyDocumentMutation> {\n return requester<\n CreateEmptyDocumentMutation,\n CreateEmptyDocumentMutationVariables\n >(\n CreateEmptyDocumentDocument,\n variables,\n options,\n ) as Promise<CreateEmptyDocumentMutation>;\n },\n MutateDocument(\n variables: MutateDocumentMutationVariables,\n options?: C,\n ): Promise<MutateDocumentMutation> {\n return requester<MutateDocumentMutation, MutateDocumentMutationVariables>(\n MutateDocumentDocument,\n variables,\n options,\n ) as Promise<MutateDocumentMutation>;\n },\n MutateDocumentAsync(\n variables: MutateDocumentAsyncMutationVariables,\n options?: C,\n ): Promise<MutateDocumentAsyncMutation> {\n return requester<\n MutateDocumentAsyncMutation,\n MutateDocumentAsyncMutationVariables\n >(\n MutateDocumentAsyncDocument,\n variables,\n options,\n ) as Promise<MutateDocumentAsyncMutation>;\n },\n RenameDocument(\n variables: RenameDocumentMutationVariables,\n options?: C,\n ): Promise<RenameDocumentMutation> {\n return requester<RenameDocumentMutation, RenameDocumentMutationVariables>(\n RenameDocumentDocument,\n variables,\n options,\n ) as Promise<RenameDocumentMutation>;\n },\n SetPreferredEditor(\n variables: SetPreferredEditorMutationVariables,\n options?: C,\n ): Promise<SetPreferredEditorMutation> {\n return requester<\n SetPreferredEditorMutation,\n SetPreferredEditorMutationVariables\n >(\n SetPreferredEditorDocument,\n variables,\n options,\n ) as Promise<SetPreferredEditorMutation>;\n },\n AddRelationship(\n variables: AddRelationshipMutationVariables,\n options?: C,\n ): Promise<AddRelationshipMutation> {\n return requester<\n AddRelationshipMutation,\n AddRelationshipMutationVariables\n >(\n AddRelationshipDocument,\n variables,\n options,\n ) as Promise<AddRelationshipMutation>;\n },\n UpdateRelationship(\n variables: UpdateRelationshipMutationVariables,\n options?: C,\n ): Promise<UpdateRelationshipMutation> {\n return requester<\n UpdateRelationshipMutation,\n UpdateRelationshipMutationVariables\n >(\n UpdateRelationshipDocument,\n variables,\n options,\n ) as Promise<UpdateRelationshipMutation>;\n },\n RemoveRelationship(\n variables: RemoveRelationshipMutationVariables,\n options?: C,\n ): Promise<RemoveRelationshipMutation> {\n return requester<\n RemoveRelationshipMutation,\n RemoveRelationshipMutationVariables\n >(\n RemoveRelationshipDocument,\n variables,\n options,\n ) as Promise<RemoveRelationshipMutation>;\n },\n MoveRelationship(\n variables: MoveRelationshipMutationVariables,\n options?: C,\n ): Promise<MoveRelationshipMutation> {\n return requester<\n MoveRelationshipMutation,\n MoveRelationshipMutationVariables\n >(\n MoveRelationshipDocument,\n variables,\n options,\n ) as Promise<MoveRelationshipMutation>;\n },\n DeleteDocument(\n variables: DeleteDocumentMutationVariables,\n options?: C,\n ): Promise<DeleteDocumentMutation> {\n return requester<DeleteDocumentMutation, DeleteDocumentMutationVariables>(\n DeleteDocumentDocument,\n variables,\n options,\n ) as Promise<DeleteDocumentMutation>;\n },\n DeleteDocuments(\n variables: DeleteDocumentsMutationVariables,\n options?: C,\n ): Promise<DeleteDocumentsMutation> {\n return requester<\n DeleteDocumentsMutation,\n DeleteDocumentsMutationVariables\n >(\n DeleteDocumentsDocument,\n variables,\n options,\n ) as Promise<DeleteDocumentsMutation>;\n },\n DocumentChanges(\n variables?: DocumentChangesSubscriptionVariables,\n options?: C,\n ): AsyncIterable<DocumentChangesSubscription> {\n return requester<\n DocumentChangesSubscription,\n DocumentChangesSubscriptionVariables\n >(\n DocumentChangesDocument,\n variables,\n options,\n ) as AsyncIterable<DocumentChangesSubscription>;\n },\n JobChanges(\n variables: JobChangesSubscriptionVariables,\n options?: C,\n ): AsyncIterable<JobChangesSubscription> {\n return requester<JobChangesSubscription, JobChangesSubscriptionVariables>(\n JobChangesDocument,\n variables,\n options,\n ) as AsyncIterable<JobChangesSubscription>;\n },\n PollSyncEnvelopes(\n variables: PollSyncEnvelopesQueryVariables,\n options?: C,\n ): Promise<PollSyncEnvelopesQuery> {\n return requester<PollSyncEnvelopesQuery, PollSyncEnvelopesQueryVariables>(\n PollSyncEnvelopesDocument,\n variables,\n options,\n ) as Promise<PollSyncEnvelopesQuery>;\n },\n TouchChannel(\n variables: TouchChannelMutationVariables,\n options?: C,\n ): Promise<TouchChannelMutation> {\n return requester<TouchChannelMutation, TouchChannelMutationVariables>(\n TouchChannelDocument,\n variables,\n options,\n ) as Promise<TouchChannelMutation>;\n },\n PushSyncEnvelopes(\n variables: PushSyncEnvelopesMutationVariables,\n options?: C,\n ): Promise<PushSyncEnvelopesMutation> {\n return requester<\n PushSyncEnvelopesMutation,\n PushSyncEnvelopesMutationVariables\n >(\n PushSyncEnvelopesDocument,\n variables,\n options,\n ) as Promise<PushSyncEnvelopesMutation>;\n },\n };\n}\nexport type Sdk = ReturnType<typeof getSdk>;\n","import {\n type JobInfo as ClientJobInfo,\n type DocumentChangeEvent,\n type DocumentRelationship,\n type Evaluation,\n type PagedResults,\n PropagationMode,\n} from \"@powerhousedao/reactor\";\nimport { camelCase } from \"change-case\";\nimport type {\n Action,\n ActionContext,\n ActionSigner,\n DocumentModelModule,\n DocumentModelPHState,\n Operation,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n deserializeSignature,\n serializeSignature,\n} from \"@powerhousedao/shared/document-model\";\nimport { GraphQLError } from \"graphql\";\nimport { MalformedStoredOperationError } from \"../errors.js\";\nimport {\n type ActionInput,\n type ActionEvaluation as GqlActionEvaluation,\n AuthDecision as GqlAuthDecision,\n type DocumentModelResultPage,\n type DocumentRelationship as GqlDocumentRelationship,\n type DocumentRelationshipResultPage as GqlDocumentRelationshipResultPage,\n type DocumentChangeEvent as GqlDocumentChangeEvent,\n type DocumentModelGlobalState as GqlDocumentModelGlobalState,\n type JobInfo as GqlJobInfo,\n type PhDocument,\n type PhDocumentResultPage,\n PropagationMode as GqlPropagationMode,\n type ReactorOperation,\n type ReactorOperationResultPage,\n} from \"./gen/graphql.js\";\n\n/**\n * Converts a PagedResults from ReactorClient to the GraphQL DocumentModelResultPage format\n */\nexport function toDocumentModelResultPage(\n result: PagedResults<DocumentModelModule>,\n): DocumentModelResultPage {\n const models = result.results.map((module) => module.documentModel);\n return {\n cursor: result.nextCursor ?? null,\n hasNextPage: !!result.nextCursor,\n hasPreviousPage: !!result.options.cursor,\n items: models.map(toGqlDocumentModelState),\n };\n}\n\n/**\n * Gets the namespace from a DocumentModelGlobalState\n */\nfunction getNamespace(model: DocumentModelPHState): string {\n return model.global.name.split(\"/\")[0];\n}\n\n/**\n * Converts a DocumentModelGlobalState from ReactorClient to GraphQL format\n */\nfunction toGqlDocumentModelState(\n model: DocumentModelPHState,\n): GqlDocumentModelGlobalState {\n const global = model.global;\n const specification =\n global.specifications.length > 0 ? global.specifications[0] : {};\n const namespace = getNamespace(model);\n\n return {\n id: global.id,\n name: global.name,\n namespace,\n specification,\n version: null,\n };\n}\n\n/**\n * Converts a PagedResults of PHDocument to GraphQL PhDocumentResultPage format\n */\nexport function toPhDocumentResultPage(\n result: PagedResults<PHDocument>,\n): PhDocumentResultPage {\n return {\n cursor: result.nextCursor ?? null,\n hasNextPage: !!result.nextCursor,\n hasPreviousPage: !!result.options.cursor,\n items: result.results.map(toGqlPhDocument),\n };\n}\n\n/**\n * Converts a relationship edge from the indexer to GraphQL format.\n */\nexport function toGqlDocumentRelationship(\n relationship: DocumentRelationship,\n): GqlDocumentRelationship {\n return {\n sourceId: relationship.sourceId,\n targetId: relationship.targetId,\n relationshipType: relationship.relationshipType,\n metadata: relationship.metadata ?? null,\n createdAt: relationship.createdAt,\n updatedAt: relationship.updatedAt,\n };\n}\n\n/**\n * Converts a PagedResults of relationship edges to GraphQL\n * DocumentRelationshipResultPage format\n */\nexport function toDocumentRelationshipResultPage(\n result: PagedResults<DocumentRelationship>,\n): GqlDocumentRelationshipResultPage {\n return {\n cursor: result.nextCursor ?? null,\n hasNextPage: !!result.nextCursor,\n hasPreviousPage: !!result.options.cursor,\n items: result.results.map(toGqlDocumentRelationship),\n };\n}\n\n/**\n * Converts a PHDocument from ReactorClient to GraphQL PhDocument format\n */\nexport function toGqlPhDocument(doc: PHDocument): PhDocument {\n const revisionsList = Object.entries(doc.header.revision).map(\n ([scope, revision]) => ({\n scope,\n revision,\n }),\n );\n\n return {\n id: doc.header.id,\n name: doc.header.name,\n documentType: doc.header.documentType,\n slug: doc.header.slug,\n preferredEditor: doc.header.meta?.preferredEditor ?? null,\n createdAtUtcIso: doc.header.createdAtUtcIso,\n lastModifiedAtUtcIso: doc.header.lastModifiedAtUtcIso,\n revisionsList,\n state: doc.state,\n };\n}\n\n/**\n * Converts JobInfo from ReactorClient to GraphQL format\n */\nexport function toGqlJobInfo(job: ClientJobInfo): GqlJobInfo {\n return {\n id: job.id,\n status: job.status,\n createdAt: job.createdAtUtcIso,\n completedAt: job.completedAtUtcIso ?? null,\n error: job.error?.message ?? null,\n result: job.result ?? null,\n };\n}\n\n/**\n * Handles nullable/undefined conversion for GraphQL InputMaybe types\n */\nexport function fromInputMaybe<T>(value: T | null | undefined): T | undefined {\n return value === null ? undefined : value;\n}\n\n/**\n * Maps GraphQL PropagationMode enum to reactor PropagationMode enum.\n * The GQL enum uses uppercase values (\"CASCADE\") while the reactor\n * enum uses lowercase values (\"cascade\").\n */\nexport function toReactorPropagationMode(\n gqlMode: GqlPropagationMode | null | undefined,\n): PropagationMode | undefined {\n if (gqlMode == null) {\n return undefined;\n }\n switch (gqlMode) {\n case GqlPropagationMode.Cascade:\n return PropagationMode.Cascade;\n case GqlPropagationMode.Orphan:\n return PropagationMode.None;\n }\n}\n\n/**\n * Maps one predicted verdict to its GraphQL shape. A refusal's reason is the\n * consensus string the reactor would record for it, carried through verbatim so\n * a client can tell a deletion refusal from a missing grant; an allow has none.\n */\nexport function toGqlActionEvaluation(\n evaluation: Evaluation,\n): GqlActionEvaluation {\n return evaluation.decision === \"allow\"\n ? { decision: GqlAuthDecision.Allow, reason: null }\n : { decision: GqlAuthDecision.Deny, reason: evaluation.reason };\n}\n\n/**\n * Converts readonly arrays to mutable arrays for ReactorClient\n */\nexport function toMutableArray<T>(\n arr: readonly T[] | undefined,\n): T[] | undefined {\n return arr ? [...arr] : undefined;\n}\n\n/**\n * Validates that an incoming value has the structure of an Action.\n *\n * This is the whole guard on the way in. `mutateDocument` takes untyped JSON, so\n * nothing has checked these fields before a resolver runs, and the id in\n * particular has to be checked here: it is hashed into the operation id and\n * replay dedupes by it, so an action without one is stored under an operation id\n * shared by every id-less operation on the same document, scope and branch.\n *\n * The storage constraint would refuse such a row anyway, but only after a job\n * has been enqueued and failed. Refusing here answers the caller instead.\n */\nfunction validateActionStructure(obj: unknown): obj is Action {\n if (!obj || typeof obj !== \"object\") {\n return false;\n }\n\n const action = obj as Record<string, unknown>;\n\n // Required fields\n if (typeof action.id !== \"string\" || !action.id) {\n return false;\n }\n\n if (typeof action.type !== \"string\" || !action.type) {\n return false;\n }\n\n if (typeof action.scope !== \"string\" || !action.scope) {\n return false;\n }\n\n if (typeof action.timestampUtcMs !== \"string\" || !action.timestampUtcMs) {\n return false;\n }\n\n // input can be anything (unknown)\n if (!(\"input\" in action)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Restores an action's signatures to the tuples verification reads.\n *\n * A signature is a five-param tuple, and GraphQL declares `signatures` as a\n * list of strings, so a client joins each one for transport. The sync path\n * already splits them on arrival; this is the same step for the mutation path,\n * which had none - an action submitted there kept whatever shape it arrived in,\n * so the same signature was persisted as a tuple or as one joined string\n * depending on which door it came through.\n *\n * A tuple passes through untouched, so an in-process caller handing over real\n * signatures is unaffected.\n */\nfunction withDeserializedSignatures(action: Action): Action {\n const signer = action.context?.signer;\n if (!signer?.signatures || signer.signatures.length === 0) {\n return action;\n }\n\n return {\n ...action,\n context: {\n ...action.context,\n signer: {\n ...signer,\n signatures: signer.signatures.map(deserializeSignature),\n },\n },\n };\n}\n\n/**\n * Converts actions the schema has already coerced into the actions the reactor\n * applies.\n *\n * The one conversion the schema cannot express is the signature: GraphQL\n * declares `signatures` as a list of strings, not of lists, so each arrives\n * joined and has to be read back as the tuple verification indexes into.\n *\n * Nothing is validated here. `ActionInput` states every field the reactor needs,\n * so anything that reached this point has them - unlike the untyped path, which\n * has to check by hand.\n */\nexport function toSubmittableActions(\n actions: readonly ActionInput[],\n): Action[] {\n return actions.map((action) => {\n const context = toSubmittableContext(action.context);\n const submittable: Action = {\n id: action.id,\n type: action.type,\n timestampUtcMs: action.timestampUtcMs,\n input: action.input,\n scope: action.scope,\n };\n return context ? { ...submittable, context } : submittable;\n });\n}\n\n/**\n * `ReactorSignerInput` leaves `user` and `app` optional where `ActionSigner`\n * requires them, so an incomplete signer cannot be represented. It is carried\n * through as it arrived rather than filled in: the signature verifier is what\n * should refuse it, and inventing either field here would be inventing the part\n * that says who signed.\n */\nfunction toSubmittableContext(\n context: ActionInput[\"context\"],\n): ActionContext | undefined {\n if (!context) {\n return undefined;\n }\n\n const submittable: ActionContext = {};\n const prevOpIndex = fromInputMaybe(context.prevOpIndex);\n if (prevOpIndex !== undefined) {\n submittable.prevOpIndex = prevOpIndex;\n }\n const prevOpHash = fromInputMaybe(context.prevOpHash);\n if (prevOpHash !== undefined) {\n submittable.prevOpHash = prevOpHash;\n }\n const nonce = fromInputMaybe(context.nonce);\n if (nonce !== undefined) {\n submittable.nonce = nonce;\n }\n\n const signer = fromInputMaybe(context.signer);\n if (signer) {\n submittable.signer = {\n user: fromInputMaybe(signer.user),\n app: fromInputMaybe(signer.app),\n signatures: signer.signatures.map(deserializeSignature),\n } as ActionSigner;\n }\n\n return Object.keys(submittable).length > 0 ? submittable : undefined;\n}\n\n/**\n * Converts a JSONObject to an Action, validating basic structure\n */\nexport function jsonObjectToAction(obj: unknown): Action {\n if (!validateActionStructure(obj)) {\n throw new GraphQLError(\n \"Invalid action structure. Actions must have: id (string), type (string), \" +\n \"scope (string), timestampUtcMs (string), and input (any)\",\n );\n }\n\n return withDeserializedSignatures(obj as Action);\n}\n\n/**\n * Validates an action against its document model\n * Based on validateDocumentModelAction from reactor-mcp\n */\nexport function validateDocumentModelAction(\n documentModelModule: DocumentModelModule,\n action: Action,\n): { isValid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n const globalState = documentModelModule.documentModel.global;\n\n // Get the latest specification\n if (!globalState.specifications || globalState.specifications.length === 0) {\n errors.push(\"Document model has no specifications\");\n return { isValid: false, errors };\n }\n\n const latestSpec =\n globalState.specifications[globalState.specifications.length - 1];\n\n // Search through modules to find the operation that matches the action type (in SCREAMING_SNAKE_CASE)\n let operation: (Operation & { scope: string }) | null = null;\n\n for (const module of latestSpec.modules) {\n const unsafeOperationOrActionOrSomething = module.operations.find(\n (op) => op.name === action.type,\n ) as unknown as Operation & { scope: string };\n if (unsafeOperationOrActionOrSomething) {\n operation = unsafeOperationOrActionOrSomething;\n break;\n }\n }\n\n if (!operation) {\n errors.push(\n `Operation \"${action.type}\" is not defined in any module of the document model`,\n );\n return { isValid: false, errors };\n }\n\n // Convert action type from SCREAMING_SNAKE_CASE to camelCase to match action creators\n const camelCaseActionType = camelCase(action.type);\n\n // Check if action creator exists in documentModelModule.actions\n const actionCreator = documentModelModule.actions[camelCaseActionType];\n\n if (!actionCreator) {\n errors.push(\n `Action creator \"${camelCaseActionType}\" for action type \"${action.type}\" is not defined in document model module actions`,\n );\n return { isValid: false, errors };\n }\n\n // Validate the operation using the action creator\n let inputError: Error | null = null;\n try {\n actionCreator(action.input);\n } catch (e) {\n inputError = e instanceof Error ? e : new Error(JSON.stringify(e));\n }\n\n if (inputError) {\n errors.push(`Input validation error: ${inputError.message}`);\n }\n\n // Validate scope if operation defines one\n if (operation.scope && action.scope !== operation.scope) {\n errors.push(\n `Action scope \"${action.scope}\" does not match operation scope \"${operation.scope}\"`,\n );\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * Validates a list of actions by converting them from JSON and checking structure\n */\nexport function validateActions(actions: readonly unknown[]): Action[] {\n const convertedActions: Action[] = [];\n for (let i = 0; i < actions.length; i++) {\n try {\n convertedActions.push(jsonObjectToAction(actions[i]));\n } catch (error) {\n throw new GraphQLError(\n `Action at index ${i}: ${error instanceof Error ? error.message : \"Invalid action structure\"}`,\n );\n }\n }\n return convertedActions;\n}\n\n/** The operation fields the schema declares non-null. */\nconst REQUIRED_OPERATION_FIELDS = [\n \"index\",\n \"timestampUtcMs\",\n \"hash\",\n \"skip\",\n] as const;\n\n/** The action fields the schema declares non-null. */\nconst REQUIRED_ACTION_FIELDS = [\n \"id\",\n \"type\",\n \"timestampUtcMs\",\n \"input\",\n \"scope\",\n] as const;\n\n/**\n * An operation as storage actually hands it over.\n *\n * `rowToOperation` casts a jsonb column straight to `Operation`, so every field\n * the declared type promises is present may be absent at runtime - that cast is\n * why TypeScript never caught this. Read through this view instead, or the\n * checks below look impossible to the compiler.\n */\ntype StoredOperation = Record<string, unknown> & {\n action?: Record<string, unknown> | null;\n};\n\n/**\n * Names an operation well enough to find the row it came from, without assuming\n * the fields that might be the missing ones.\n */\nfunction describeOperation(stored: StoredOperation): string {\n const parts = [\n typeof stored.id === \"string\" && stored.id\n ? `operation ${stored.id}`\n : \"operation with no id\",\n ];\n if (typeof stored.index === \"number\") {\n parts.push(`index ${stored.index}`);\n }\n const scope = stored.action?.scope;\n if (typeof scope === \"string\" && scope) {\n parts.push(`scope ${scope}`);\n }\n return parts.join(\", \");\n}\n\n/**\n * Refuses an operation the schema cannot represent, naming the field.\n *\n * The alternative is what execution does unaided: nullify the field, bubble that\n * up the non-null chain until it takes out the envelope's whole operation list,\n * and report a bare \"Cannot return null for non-nullable field\" with no way to\n * tell which of a hundred operations was at fault. Checked before the response\n * is built so the failure is typed and attributable.\n *\n * Presence is all that is checked. The schema's own serialization still rejects\n * a value of the wrong type, and inventing further rules here would put a second\n * contract beside the one the schema already states.\n */\nfunction assertServable(operation: Operation): void {\n const stored = operation as unknown as StoredOperation;\n\n for (const field of REQUIRED_OPERATION_FIELDS) {\n if (stored[field] === undefined || stored[field] === null) {\n throw new MalformedStoredOperationError(\n `${describeOperation(stored)} has no ${field}`,\n );\n }\n }\n\n const action = stored.action;\n if (action === undefined || action === null) {\n throw new MalformedStoredOperationError(\n `${describeOperation(stored)} has no action`,\n );\n }\n\n for (const field of REQUIRED_ACTION_FIELDS) {\n if (action[field] === undefined || action[field] === null) {\n throw new MalformedStoredOperationError(\n `${describeOperation(stored)} has an action with no ${field}`,\n );\n }\n }\n}\n\n/**\n * Transforms an operation to serialize signatures from tuples to strings for GraphQL compatibility.\n */\nexport function serializeOperationForGraphQL(\n operation: Operation,\n): ReactorOperation {\n assertServable(operation);\n\n const signer = operation.action.context?.signer;\n if (!signer?.signatures) {\n return operation as unknown as ReactorOperation;\n }\n\n return {\n ...operation,\n action: {\n ...operation.action,\n context: {\n ...operation.action.context,\n signer: {\n ...signer,\n signatures: signer.signatures.map(serializeSignature),\n },\n },\n },\n } as unknown as ReactorOperation;\n}\n\n/**\n * Converts a PagedResults of Operation to GraphQL ReactorOperationResultPage format\n */\nexport function toOperationResultPage(\n result: PagedResults<Operation>,\n): ReactorOperationResultPage {\n return {\n cursor: result.nextCursor ?? null,\n hasNextPage: !!result.nextCursor,\n hasPreviousPage: !!result.options.cursor && result.options.cursor !== \"0\",\n items: result.results.map(serializeOperationForGraphQL),\n };\n}\n\nexport function toGqlDocumentChangeEvent(\n event: DocumentChangeEvent,\n): GqlDocumentChangeEvent {\n const typeMap: Record<string, string> = {\n created: \"CREATED\",\n deleted: \"DELETED\",\n updated: \"UPDATED\",\n parent_added: \"PARENT_ADDED\",\n parent_removed: \"PARENT_REMOVED\",\n child_added: \"CHILD_ADDED\",\n child_removed: \"CHILD_REMOVED\",\n };\n\n const mappedType = typeMap[event.type];\n if (!mappedType) {\n throw new GraphQLError(`Unknown document change type: ${event.type}`);\n }\n\n return {\n type: mappedType as GqlDocumentChangeEvent[\"type\"],\n documents: event.documents.map(toGqlPhDocument),\n context: event.context\n ? {\n parentId: event.context.parentId ?? null,\n childId: event.context.childId ?? null,\n }\n : null,\n };\n}\n\n/**\n * Distinct document ids a change event references: affected documents plus the\n * parent/child ids in `context` (delete/relationship events carry only context).\n */\nexport function collectChangedDocumentIds(\n event: DocumentChangeEvent,\n): string[] {\n const ids = new Set<string>();\n for (const doc of event.documents) {\n if (doc.header.id) ids.add(doc.header.id);\n }\n if (event.context?.parentId) ids.add(event.context.parentId);\n if (event.context?.childId) ids.add(event.context.childId);\n return [...ids];\n}\n\nexport function matchesSearchFilter(\n event: DocumentChangeEvent,\n search: { type?: string | null; parentId?: string | null },\n): boolean {\n if (search.type) {\n const matchesType = event.documents.some(\n (doc) => doc.header.documentType === search.type,\n );\n if (!matchesType) {\n return false;\n }\n }\n\n if (search.parentId) {\n if (\n !event.context?.parentId ||\n event.context.parentId !== search.parentId\n ) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function matchesJobFilter(\n payload: { jobId: string },\n args: { jobId: string },\n): boolean {\n return payload.jobId === args.jobId;\n}\n","import { DEFAULT_DRIVE_CONTAINER_TYPES } from \"@powerhousedao/reactor\";\n\n/**\n * Legacy document-drive document type. Use {@link isDriveContainerType} for\n * drive-container gates; this constant is kept for places (e.g. legacy\n * default-drive bootstrap) that genuinely need the specific document-drive\n * type rather than \"any drive container\".\n */\nexport const DRIVE_DOCUMENT_TYPE = \"powerhouse/document-drive\";\n\n/**\n * Returns true when the given document type represents a drive container.\n * Delegates to the reactor's `DEFAULT_DRIVE_CONTAINER_TYPES`, so both the\n * legacy `powerhouse/document-drive` and the newer `powerhouse/reactor-drive`\n * count.\n */\nexport function isDriveContainerType(documentType: string): boolean {\n return DEFAULT_DRIVE_CONTAINER_TYPES.has(documentType);\n}\n","import {\n type ActionCandidate,\n type ActionEvaluations,\n AuthEnforcementDisabledError,\n consolidateSyncOperations,\n type DocumentRelationship,\n DriveCollectionId,\n envelopesToSyncOperations,\n type IDriveClient,\n type IReactorClient,\n type ISyncManager,\n type JobInfo,\n JobStatus,\n type OperationFilter,\n type PagedResults,\n type PagingOptions,\n type RemoteFilter,\n type SearchFilter,\n syncOperationErrorType,\n type SyncOperation,\n type SyncScopeGate,\n type ViewFilter,\n} from \"@powerhousedao/reactor\";\nimport type {\n AuthSubject,\n DocumentModelModule,\n Operation,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { withSignaturePolicy } from \"@powerhousedao/shared/document-model\";\nimport { GraphQLError } from \"graphql\";\n\nimport { AuthEvaluationUnsupportedError } from \"../errors.js\";\nimport { isDriveContainerType } from \"./constants.js\";\n\nconst REACTOR_DRIVE_DOCUMENT_TYPE = \"powerhouse/reactor-drive\";\n\n/**\n * Returns the drive client to use for the given drive-container parent type.\n * Throws when the parent is a reactor-drive container but no\n * `reactorDriveClient` was provided.\n */\nfunction pickDriveClient(\n reactorClient: IReactorClient,\n driveContainerType: string,\n reactorDriveClient: IDriveClient | undefined,\n): IDriveClient {\n if (driveContainerType === REACTOR_DRIVE_DOCUMENT_TYPE) {\n if (!reactorDriveClient) {\n throw new GraphQLError(\n \"Reactor-drive parent encountered but no reactorDriveClient is configured on this switchboard\",\n );\n }\n return reactorDriveClient;\n }\n return reactorClient.drives;\n}\n\n/**\n * A mutation's document re-read as the caller, since the client reads it back\n * as its signer. A caller who may write but not read gets it stripped.\n */\nasync function readAsCaller(\n reactorClient: IReactorClient,\n document: PHDocument,\n subject: AuthSubject | undefined,\n branch?: string,\n): Promise<PHDocument> {\n if (!subject) {\n return document;\n }\n try {\n return await reactorClient.get(document.header.id, { subject, branch });\n } catch (error) {\n throw new GraphQLError(\n `Failed to read the document back: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport const MAX_OPERATIONS_PER_ENVELOPE = 25;\nexport const MAX_OPERATIONS_PER_PAGE = 100;\nimport {\n fromInputMaybe,\n serializeOperationForGraphQL,\n toDocumentRelationshipResultPage,\n toGqlActionEvaluation,\n toDocumentModelResultPage,\n toGqlJobInfo,\n toSubmittableActions,\n toGqlPhDocument,\n toMutableArray,\n toOperationResultPage,\n toPhDocumentResultPage,\n toReactorPropagationMode,\n validateActions,\n} from \"./adapters.js\";\nimport type {\n ActionEvaluations as GqlActionEvaluations,\n ActionInput,\n DocumentModelResultPage,\n DocumentRelationshipResultPage,\n JobInfo as GqlJobInfo,\n PropagationMode as GqlPropagationMode,\n PhDocumentResultPage,\n ReactorOperationResultPage,\n} from \"./gen/graphql.js\";\n\nexport async function documentModels(\n reactorClient: IReactorClient,\n args: {\n namespace?: string | null;\n paging?: {\n cursor?: string | null;\n limit?: number | null;\n } | null;\n },\n): Promise<DocumentModelResultPage> {\n const namespace = fromInputMaybe(args.namespace);\n\n let paging: PagingOptions | undefined;\n if (args.paging) {\n const cursor = fromInputMaybe(args.paging.cursor);\n const limit = fromInputMaybe(args.paging.limit);\n if (cursor || limit) {\n paging = {\n cursor: cursor || \"\",\n limit: limit || 10,\n };\n }\n }\n\n let result: PagedResults<DocumentModelModule>;\n try {\n result = await reactorClient.getDocumentModelModules(namespace, paging);\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch document models: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toDocumentModelResultPage(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert document models to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function document(\n reactorClient: IReactorClient,\n args: {\n identifier: string;\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<{\n document: ReturnType<typeof toGqlPhDocument>;\n childIds: string[];\n}> {\n let view: ViewFilter | undefined = subject ? { subject } : undefined;\n if (args.view) {\n view = {\n subject,\n branch: fromInputMaybe(args.view.branch),\n scopes: toMutableArray(fromInputMaybe(args.view.scopes)),\n };\n }\n\n let result: PHDocument;\n try {\n result = await reactorClient.get(args.identifier, view);\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch document: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n let children: PagedResults<PHDocument>;\n try {\n children = await reactorClient.getOutgoingRelationships(\n args.identifier,\n \"child\",\n view,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch children: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return {\n document: toGqlPhDocument(result),\n childIds: children.results.map((child) => child.header.id),\n };\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function documentOutgoingRelationships(\n reactorClient: IReactorClient,\n args: {\n sourceIdentifier: string;\n relationshipType: string;\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n paging?: {\n cursor?: string | null;\n limit?: number | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<PhDocumentResultPage> {\n let view: ViewFilter | undefined = subject ? { subject } : undefined;\n if (args.view) {\n view = {\n subject,\n branch: fromInputMaybe(args.view.branch),\n scopes: toMutableArray(fromInputMaybe(args.view.scopes)),\n };\n }\n\n let paging: PagingOptions | undefined;\n if (args.paging) {\n const cursor = fromInputMaybe(args.paging.cursor);\n const limit = fromInputMaybe(args.paging.limit);\n if (cursor || limit) {\n paging = {\n cursor: cursor || \"\",\n limit: limit || 10,\n };\n }\n }\n\n let result: PagedResults<PHDocument>;\n try {\n result = await reactorClient.getOutgoingRelationships(\n args.sourceIdentifier,\n args.relationshipType,\n view,\n paging,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch outgoing relationships: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toPhDocumentResultPage(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert outgoing relationships to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function documentIncomingRelationships(\n reactorClient: IReactorClient,\n args: {\n targetIdentifier: string;\n relationshipType: string;\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n paging?: {\n cursor?: string | null;\n limit?: number | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<PhDocumentResultPage> {\n let view: ViewFilter | undefined = subject ? { subject } : undefined;\n if (args.view) {\n view = {\n subject,\n branch: fromInputMaybe(args.view.branch),\n scopes: toMutableArray(fromInputMaybe(args.view.scopes)),\n };\n }\n\n let paging: PagingOptions | undefined;\n if (args.paging) {\n const cursor = fromInputMaybe(args.paging.cursor);\n const limit = fromInputMaybe(args.paging.limit);\n if (cursor || limit) {\n paging = {\n cursor: cursor || \"\",\n limit: limit || 10,\n };\n }\n }\n\n let result: PagedResults<PHDocument>;\n try {\n result = await reactorClient.getIncomingRelationships(\n args.targetIdentifier,\n args.relationshipType,\n view,\n paging,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch incoming relationships: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toPhDocumentResultPage(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert incoming relationships to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function documentOutgoingRelationshipEdges(\n reactorClient: IReactorClient,\n args: {\n sourceIdentifier: string;\n relationshipType?: string | null;\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n paging?: {\n cursor?: string | null;\n limit?: number | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<DocumentRelationshipResultPage> {\n const view = toRelationshipViewFilter(args.view, subject);\n const paging = toRelationshipPagingOptions(args.paging);\n\n let result: PagedResults<DocumentRelationship>;\n try {\n result = await reactorClient.getOutgoingRelationshipEdges(\n args.sourceIdentifier,\n fromInputMaybe(args.relationshipType),\n view,\n paging,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch outgoing relationship edges: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toDocumentRelationshipResultPage(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert outgoing relationship edges to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function documentIncomingRelationshipEdges(\n reactorClient: IReactorClient,\n args: {\n targetIdentifier: string;\n relationshipType?: string | null;\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n paging?: {\n cursor?: string | null;\n limit?: number | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<DocumentRelationshipResultPage> {\n const view = toRelationshipViewFilter(args.view, subject);\n const paging = toRelationshipPagingOptions(args.paging);\n\n let result: PagedResults<DocumentRelationship>;\n try {\n result = await reactorClient.getIncomingRelationshipEdges(\n args.targetIdentifier,\n fromInputMaybe(args.relationshipType),\n view,\n paging,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch incoming relationship edges: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toDocumentRelationshipResultPage(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert incoming relationship edges to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nfunction toRelationshipViewFilter(\n input:\n | {\n branch?: string | null;\n scopes?: readonly string[] | null;\n }\n | null\n | undefined,\n subject?: AuthSubject,\n): ViewFilter | undefined {\n if (!input) {\n return subject ? { subject } : undefined;\n }\n\n return {\n subject,\n branch: fromInputMaybe(input.branch),\n scopes: toMutableArray(fromInputMaybe(input.scopes)),\n };\n}\n\nfunction toRelationshipPagingOptions(\n input:\n | {\n cursor?: string | null;\n limit?: number | null;\n }\n | null\n | undefined,\n): PagingOptions | undefined {\n if (!input) {\n return undefined;\n }\n\n const cursor = fromInputMaybe(input.cursor);\n const limit = fromInputMaybe(input.limit);\n if (!cursor && !limit) {\n return undefined;\n }\n\n return { cursor: cursor || \"\", limit: limit || 10 };\n}\n\nexport async function findDocuments(\n reactorClient: IReactorClient,\n args: {\n search: {\n type?: string | null;\n parentId?: string | null;\n };\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n paging?: {\n cursor?: string | null;\n limit?: number | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<PhDocumentResultPage> {\n let view: ViewFilter | undefined = subject ? { subject } : undefined;\n if (args.view) {\n view = {\n subject,\n branch: fromInputMaybe(args.view.branch),\n scopes: toMutableArray(fromInputMaybe(args.view.scopes)),\n };\n }\n\n let paging: PagingOptions | undefined;\n if (args.paging) {\n const cursor = fromInputMaybe(args.paging.cursor);\n const limit = fromInputMaybe(args.paging.limit);\n if (cursor || limit) {\n paging = {\n cursor: cursor || \"\",\n limit: limit || 10,\n };\n }\n }\n\n const search: SearchFilter = {\n type: fromInputMaybe(args.search.type),\n parentId: fromInputMaybe(args.search.parentId),\n };\n\n let result: PagedResults<PHDocument>;\n try {\n result = await reactorClient.find(search, view, paging);\n } catch (error) {\n throw new GraphQLError(\n `Failed to find documents: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toPhDocumentResultPage(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert documents to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\n/**\n * The answer for a job the caller may not see, shaped as the reactor answers\n * an unknown one so that the two cannot be told apart.\n */\nfunction unknownJob(jobId: string): JobInfo {\n const now = new Date().toISOString();\n return {\n id: jobId,\n documentId: \"\",\n status: JobStatus.FAILED,\n createdAtUtcIso: now,\n completedAtUtcIso: now,\n error: { name: \"Error\", message: \"Job not found\", stack: \"\" },\n consistencyToken: { version: 1, createdAtUtcIso: now, coordinates: [] },\n meta: { batchId: jobId, batchJobIds: [jobId] },\n };\n}\n\nexport async function jobStatus(\n reactorClient: IReactorClient,\n args: {\n jobId: string;\n },\n serves: (documentId: string) => Promise<boolean>,\n): Promise<GqlJobInfo> {\n let result: JobInfo;\n try {\n result = await reactorClient.getJobStatus(args.jobId);\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch job status: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n if (!(await serves(result.documentId))) {\n result = unknownJob(args.jobId);\n }\n\n try {\n return toGqlJobInfo(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert job status to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function documentOperations(\n reactorClient: IReactorClient,\n args: {\n filter: {\n documentId: string;\n branch?: string | null;\n scopes?: readonly string[] | null;\n actionTypes?: readonly string[] | null;\n sinceRevision?: number | null;\n timestampFrom?: string | null;\n timestampTo?: string | null;\n };\n paging?: {\n cursor?: string | null;\n limit?: number | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<ReactorOperationResultPage> {\n let view: ViewFilter | undefined = subject ? { subject } : undefined;\n const branch = fromInputMaybe(args.filter.branch);\n const scopes = toMutableArray(fromInputMaybe(args.filter.scopes));\n if (branch || scopes) {\n view = { subject, branch, scopes };\n }\n\n const actionTypes = toMutableArray(fromInputMaybe(args.filter.actionTypes));\n const sinceRevision = fromInputMaybe(args.filter.sinceRevision);\n const timestampFrom = fromInputMaybe(args.filter.timestampFrom);\n const timestampTo = fromInputMaybe(args.filter.timestampTo);\n\n let operationFilter: OperationFilter | undefined;\n if (\n (actionTypes && actionTypes.length > 0) ||\n sinceRevision !== undefined ||\n timestampFrom ||\n timestampTo\n ) {\n operationFilter = {\n actionTypes:\n actionTypes && actionTypes.length > 0 ? actionTypes : undefined,\n sinceRevision,\n timestampFrom: timestampFrom || undefined,\n timestampTo: timestampTo || undefined,\n };\n }\n\n let paging: PagingOptions | undefined;\n if (args.paging) {\n const cursor = fromInputMaybe(args.paging.cursor);\n const limit = fromInputMaybe(args.paging.limit);\n if (cursor || limit) {\n paging = {\n cursor: cursor || \"\",\n limit: limit || 100,\n };\n }\n }\n\n let result: PagedResults<Operation>;\n try {\n result = await reactorClient.getOperations(\n args.filter.documentId,\n view,\n operationFilter,\n paging,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch document operations: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toOperationResultPage(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert operations to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\n/**\n * Predicts the admission verdict for each candidate operation, deciding against\n * the document policy through the reactor's own decision model.\n *\n * The subject is supplied by the subgraph from the authenticated request, never\n * by the caller: answering for an arbitrary subject would disclose what a policy\n * grants somebody else. It carries the caller's address and the app key their\n * token authenticated with, which is the same pair a signed action presents, so\n * a grant naming either matches here exactly as it would at admission.\n *\n * A reactor without authEnforcement raises the named error, which becomes an\n * \"unsupported\" code rather than a denial.\n */\nexport async function evaluateActions(\n reactorClient: IReactorClient,\n args: {\n documentIdentifier: string;\n branch?: string | null;\n candidates: ReadonlyArray<{\n scope: string;\n type: string;\n input?: unknown;\n }>;\n },\n subject?: AuthSubject,\n): Promise<GqlActionEvaluations> {\n const branch = fromInputMaybe(args.branch) ?? \"main\";\n const candidates: ActionCandidate[] = args.candidates.map((candidate) => ({\n scope: candidate.scope,\n type: candidate.type,\n input: fromInputMaybe(candidate.input),\n }));\n\n let result: ActionEvaluations;\n try {\n result = await reactorClient.evaluateActions(\n args.documentIdentifier,\n branch,\n candidates,\n subject,\n );\n } catch (error) {\n if (AuthEnforcementDisabledError.isError(error)) {\n throw new AuthEvaluationUnsupportedError();\n }\n throw new GraphQLError(\n `Failed to evaluate actions: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n return {\n evaluations: result.evaluations.map(toGqlActionEvaluation),\n allAllowed: result.allAllowed,\n anyAllowed: result.anyAllowed,\n allDenied: result.allDenied,\n anyDenied: result.anyDenied,\n };\n}\n\nexport async function createDocument(\n reactorClient: IReactorClient,\n args: {\n document: unknown;\n parentIdentifier?: string | null;\n },\n reactorDriveClient?: IDriveClient,\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n // Validate that document is a PHDocument\n if (!args.document || typeof args.document !== \"object\") {\n throw new GraphQLError(\"Invalid document: must be an object\");\n }\n\n const document = args.document as PHDocument;\n\n // Validate required fields\n if (!document.header || typeof document.header !== \"object\") {\n throw new GraphQLError(\"Invalid document: missing or invalid header\");\n }\n\n const parentIdentifier = fromInputMaybe(args.parentIdentifier);\n\n let result: PHDocument;\n try {\n if (parentIdentifier) {\n const parent = await reactorClient.get(\n parentIdentifier,\n subject && { subject },\n );\n if (isDriveContainerType(parent.header.documentType)) {\n const driveClient = pickDriveClient(\n reactorClient,\n parent.header.documentType,\n reactorDriveClient,\n );\n result = await driveClient.addFile(parentIdentifier, document);\n } else {\n result = await reactorClient.create(document, parentIdentifier);\n }\n } else {\n result = await reactorClient.create(document);\n }\n } catch (error) {\n throw new GraphQLError(\n `Failed to create document: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = await readAsCaller(reactorClient, result, subject);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert created document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function createEmptyDocument(\n reactorClient: IReactorClient,\n args: {\n documentType: string;\n parentIdentifier?: string | null;\n name?: string | null;\n },\n reactorDriveClient?: IDriveClient,\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const parentIdentifier = fromInputMaybe(args.parentIdentifier);\n const name = fromInputMaybe(args.name);\n\n let result: PHDocument;\n try {\n if (parentIdentifier) {\n const parent = await reactorClient.get(\n parentIdentifier,\n subject && { subject },\n );\n if (isDriveContainerType(parent.header.documentType)) {\n const module = await reactorClient.getDocumentModelModule(\n args.documentType,\n );\n const document = withSignaturePolicy(\n module.utils.createDocument(),\n await reactorClient.getCreateSignaturePolicy(),\n );\n if (name) {\n document.header.name = name;\n }\n const driveClient = pickDriveClient(\n reactorClient,\n parent.header.documentType,\n reactorDriveClient,\n );\n result = await driveClient.addFile(parentIdentifier, document);\n } else {\n result = await reactorClient.createEmpty(args.documentType, {\n parentIdentifier,\n });\n }\n } else {\n result = await reactorClient.createEmpty(args.documentType, {});\n }\n } catch (error) {\n throw new GraphQLError(\n `Failed to create empty document: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = await readAsCaller(reactorClient, result, subject);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert created document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function createDocumentWithInitialState(\n reactorClient: IReactorClient,\n args: {\n documentType: string;\n parentIdentifier?: string | null;\n name?: string | null;\n slug?: string | null;\n preferredEditor?: string | null;\n initialState: Record<string, Record<string, unknown>>;\n },\n reactorDriveClient?: IDriveClient,\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const parentIdentifier = fromInputMaybe(args.parentIdentifier);\n const name = fromInputMaybe(args.name);\n const slug = fromInputMaybe(args.slug);\n const preferredEditor = fromInputMaybe(args.preferredEditor);\n\n let module: DocumentModelModule;\n try {\n module = await reactorClient.getDocumentModelModule(args.documentType);\n } catch (error) {\n throw new GraphQLError(\n `Document model not found for type ${args.documentType}: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n const document = withSignaturePolicy(\n module.utils.createDocument(),\n await reactorClient.getCreateSignaturePolicy(),\n );\n\n // Only merge specification-defined scopes (e.g., global, local).\n // Protected scopes like \"auth\" and \"document\" are excluded.\n const allowedScopes = new Set(\n Object.keys(module.documentModel.global.specifications.at(-1)?.state ?? {}),\n );\n const state = document.state as Record<string, Record<string, unknown>>;\n for (const [scope, scopeState] of Object.entries(args.initialState)) {\n if (allowedScopes.has(scope) && scope in state) {\n state[scope] = { ...state[scope], ...scopeState };\n }\n }\n\n if (name) {\n document.header.name = name;\n }\n if (slug) {\n document.header.slug = slug;\n }\n if (preferredEditor) {\n document.header.meta = { ...document.header.meta, preferredEditor };\n }\n\n let result: PHDocument;\n if (parentIdentifier) {\n let parent: PHDocument;\n try {\n parent = await reactorClient.get(\n parentIdentifier,\n subject && { subject },\n );\n } catch (error) {\n throw new GraphQLError(\n `Parent document not found: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n if (isDriveContainerType(parent.header.documentType)) {\n const driveClient = pickDriveClient(\n reactorClient,\n parent.header.documentType,\n reactorDriveClient,\n );\n try {\n result = await driveClient.addFile(parentIdentifier, document);\n } catch (error) {\n throw new GraphQLError(\n `Failed to create document in drive: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n } else {\n try {\n result = await reactorClient.create(document, parentIdentifier);\n } catch (error) {\n throw new GraphQLError(\n `Failed to create document with parent: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n }\n } else {\n try {\n result = await reactorClient.create(document);\n } catch (error) {\n throw new GraphQLError(\n `Failed to create document: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n }\n\n result = await readAsCaller(reactorClient, result, subject);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert created document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\n/** The branch a mutation applies to when the caller names none. */\nconst DEFAULT_BRANCH = \"main\";\n\n/**\n * Applies actions to a document and waits for the result.\n *\n * The wire form of `IReactorClient.execute`, and named for it. Takes the actions\n * already coerced against `ActionInput`, so the only conversion left is the one\n * the schema cannot express: a signature travels as one string, and verification\n * reads it as the tuple it was.\n */\nexport async function execute(\n reactorClient: IReactorClient,\n args: {\n documentIdentifier: string;\n actions: readonly ActionInput[];\n branch?: string | null;\n },\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const actions = toSubmittableActions(args.actions);\n const branch = fromInputMaybe(args.branch) ?? DEFAULT_BRANCH;\n\n let result: PHDocument;\n try {\n result = await reactorClient.execute(\n args.documentIdentifier,\n branch,\n actions,\n undefined,\n subject,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to execute actions: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert executed document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\n/**\n * Submits actions to a document and returns the job that will apply them.\n *\n * Returns the job rather than only its id, matching\n * `IReactorClient.executeAsync`. A job handed back from a submission has no\n * result yet, which is why `JobInfo.result` is nullable.\n */\nexport async function executeAsync(\n reactorClient: IReactorClient,\n args: {\n documentIdentifier: string;\n actions: readonly ActionInput[];\n branch?: string | null;\n },\n): Promise<GqlJobInfo> {\n const actions = toSubmittableActions(args.actions);\n const branch = fromInputMaybe(args.branch) ?? DEFAULT_BRANCH;\n\n let job: JobInfo;\n try {\n job = await reactorClient.executeAsync(\n args.documentIdentifier,\n branch,\n actions,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to submit actions: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n return toGqlJobInfo(job);\n}\n\nexport async function mutateDocument(\n reactorClient: IReactorClient,\n args: {\n documentIdentifier: string;\n actions: readonly unknown[];\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n // Validate actions\n let validatedActions;\n try {\n validatedActions = validateActions(args.actions);\n } catch (error) {\n if (error instanceof GraphQLError) {\n throw error;\n }\n throw new GraphQLError(\n `Action validation failed: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // Extract branch from view filter (default to \"main\")\n const branch = args.view?.branch ?? \"main\";\n\n let result: PHDocument;\n try {\n result = await reactorClient.execute(\n args.documentIdentifier,\n branch,\n validatedActions,\n undefined,\n subject,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to mutate document: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert mutated document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function mutateDocumentAsync(\n reactorClient: IReactorClient,\n args: {\n documentIdentifier: string;\n actions: readonly unknown[];\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n },\n): Promise<string> {\n // Validate actions\n let validatedActions;\n try {\n validatedActions = validateActions(args.actions);\n } catch (error) {\n if (error instanceof GraphQLError) {\n throw error;\n }\n throw new GraphQLError(\n `Action validation failed: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // Extract branch from view filter (default to \"main\")\n const branch = args.view?.branch ?? \"main\";\n\n let result: JobInfo;\n try {\n result = await reactorClient.executeAsync(\n args.documentIdentifier,\n branch,\n validatedActions,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to submit document mutation: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n return result.id;\n}\n\nexport async function renameDocument(\n reactorClient: IReactorClient,\n args: {\n documentIdentifier: string;\n name: string;\n branch?: string | null;\n },\n signal?: AbortSignal,\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const branch = fromInputMaybe(args.branch);\n\n let result: PHDocument;\n try {\n result = await reactorClient.rename(\n args.documentIdentifier,\n args.name,\n branch,\n signal,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to rename document: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = await readAsCaller(reactorClient, result, subject, branch);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert renamed document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function setPreferredEditor(\n reactorClient: IReactorClient,\n args: {\n documentIdentifier: string;\n preferredEditor?: string | null;\n branch?: string | null;\n },\n signal?: AbortSignal,\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const branch = fromInputMaybe(args.branch);\n const preferredEditor = fromInputMaybe(args.preferredEditor) ?? null;\n\n let result: PHDocument;\n try {\n result = await reactorClient.setPreferredEditor(\n args.documentIdentifier,\n preferredEditor,\n branch,\n signal,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to set preferred editor: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = await readAsCaller(reactorClient, result, subject, branch);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert updated document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function addRelationship(\n reactorClient: IReactorClient,\n args: {\n sourceIdentifier: string;\n targetIdentifier: string;\n relationshipType: string;\n metadata?: Record<string, unknown> | null;\n branch?: string | null;\n },\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const branch = fromInputMaybe(args.branch);\n const metadata = fromInputMaybe(args.metadata);\n\n let result: PHDocument;\n try {\n result = await reactorClient.addRelationship(\n args.sourceIdentifier,\n args.targetIdentifier,\n args.relationshipType,\n metadata,\n branch,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to add relationship: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = await readAsCaller(reactorClient, result, subject, branch);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function updateRelationship(\n reactorClient: IReactorClient,\n args: {\n sourceIdentifier: string;\n targetIdentifier: string;\n relationshipType: string;\n metadata?: Record<string, unknown> | null;\n branch?: string | null;\n },\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const branch = fromInputMaybe(args.branch);\n // The action's metadata is required and nullable: omitting it clears the edge.\n const metadata = fromInputMaybe(args.metadata) ?? null;\n\n let result: PHDocument;\n try {\n result = await reactorClient.updateRelationship(\n args.sourceIdentifier,\n args.targetIdentifier,\n args.relationshipType,\n metadata,\n branch,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to update relationship: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = await readAsCaller(reactorClient, result, subject, branch);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function removeRelationship(\n reactorClient: IReactorClient,\n args: {\n sourceIdentifier: string;\n targetIdentifier: string;\n relationshipType: string;\n branch?: string | null;\n },\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const branch = fromInputMaybe(args.branch);\n\n let result: PHDocument;\n try {\n result = await reactorClient.removeRelationship(\n args.sourceIdentifier,\n args.targetIdentifier,\n args.relationshipType,\n branch,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to remove relationship: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = await readAsCaller(reactorClient, result, subject, branch);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function moveRelationship(\n reactorClient: IReactorClient,\n args: {\n sourceParentIdentifier: string;\n targetParentIdentifier: string;\n targetIdentifier: string;\n relationshipType: string;\n branch?: string | null;\n },\n subject?: AuthSubject,\n): Promise<{\n source: ReturnType<typeof toGqlPhDocument>;\n target: ReturnType<typeof toGqlPhDocument>;\n}> {\n const branch = fromInputMaybe(args.branch);\n\n let result: { source: PHDocument; target: PHDocument };\n try {\n result = await reactorClient.moveRelationship(\n args.sourceParentIdentifier,\n args.targetParentIdentifier,\n args.targetIdentifier,\n args.relationshipType,\n branch,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to move relationship: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = {\n source: await readAsCaller(reactorClient, result.source, subject, branch),\n target: await readAsCaller(reactorClient, result.target, subject, branch),\n };\n\n try {\n return {\n source: toGqlPhDocument(result.source),\n target: toGqlPhDocument(result.target),\n };\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert documents to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function deleteDocument(\n reactorClient: IReactorClient,\n args: {\n identifier: string;\n propagate?: GqlPropagationMode | null;\n },\n reactorDriveClient?: IDriveClient,\n): Promise<boolean> {\n const propagate = toReactorPropagationMode(args.propagate);\n\n try {\n const incoming = await reactorClient.getIncomingRelationships(\n args.identifier,\n \"child\",\n );\n const driveParent = incoming.results.find((p) =>\n isDriveContainerType(p.header.documentType),\n );\n if (driveParent) {\n const driveClient = pickDriveClient(\n reactorClient,\n driveParent.header.documentType,\n reactorDriveClient,\n );\n await driveClient.removeNode(driveParent.header.id, args.identifier);\n } else {\n await reactorClient.deleteDocument(args.identifier, propagate);\n }\n return true;\n } catch (error) {\n throw new GraphQLError(\n `Failed to delete document: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function deleteDocuments(\n reactorClient: IReactorClient,\n args: {\n identifiers: readonly string[];\n propagate?: GqlPropagationMode | null;\n },\n): Promise<boolean> {\n const propagate = toReactorPropagationMode(args.propagate);\n const identifiers = [...args.identifiers];\n\n try {\n await reactorClient.deleteDocuments(identifiers, propagate);\n return true;\n } catch (error) {\n throw new GraphQLError(\n `Failed to delete documents: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\n/**\n * Registers a sync channel, or reports the state of one already registered.\n *\n * `boundAddress` claims a channel at creation for the subject that created it.\n * An anonymously created channel is left unbound, which is not a permission but\n * an unanswered question: the first authenticated subject to use it adopts it.\n */\nexport async function touchChannel(\n syncManager: ISyncManager,\n args: {\n input: {\n id: string;\n name: string;\n collectionId: string;\n filter: {\n documentId: readonly string[];\n scope: readonly string[];\n branch: string;\n };\n sinceTimestampUtcMs: string;\n };\n },\n boundAddress?: string,\n): Promise<{ success: boolean; ackOrdinal: number }> {\n try {\n const remote = syncManager.getById(args.input.id);\n\n return {\n success: true,\n ackOrdinal: remote.channel.inbox.ackOrdinal,\n };\n } catch {\n // getById will throw if the remote does not exist\n }\n\n const filter: RemoteFilter = {\n documentId: [...args.input.filter.documentId],\n scope: [...args.input.filter.scope],\n branch: args.input.filter.branch,\n };\n\n const options = {\n sinceTimestampUtcMs: args.input.sinceTimestampUtcMs,\n boundAddress,\n };\n\n try {\n await syncManager.add(\n args.input.name,\n DriveCollectionId.fromKey(args.input.collectionId),\n {\n type: \"polling\",\n parameters: {},\n },\n filter,\n options,\n args.input.id,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to create channel: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n return { success: true, ackOrdinal: 0 };\n}\n\n/**\n * The sync operations in `syncOps` this subject may not be served.\n *\n * A sync operation is one document, one branch and (from the outbox) one scope,\n * so the answer is per entry rather than per operation: an entry is withheld\n * whole or served whole, which is what keeps a scope's operation sequence\n * unbroken for whoever does receive it. A dead letter can name several scopes,\n * and is withheld only when the policy serves none of them -- the metadata\n * scopes are readable by every holder, so in practice a dead letter naming one\n * is always served.\n *\n * The policy is read once per document and branch, and the memo lives no longer\n * than this call: a poll must not answer from a policy that changed between\n * polls, since the widening case is exactly the one holding exists to serve.\n *\n * A read that fails for any reason other than the document being absent is\n * allowed to propagate. The poll then fails, the puller retries, and nothing is\n * served in the meantime -- which is the safe direction, and a visible one.\n */\nexport async function collectHeldSyncOperations(\n syncOps: ReadonlyArray<SyncOperation>,\n gate: SyncScopeGate,\n subject: AuthSubject,\n signal?: AbortSignal,\n): Promise<Set<string>> {\n const held = new Set<string>();\n const predicates = new Map<string, Promise<(scope: string) => boolean>>();\n\n for (const syncOp of syncOps) {\n const key = `${syncOp.documentId}\\u0000${syncOp.branch}`;\n let predicate = predicates.get(key);\n if (!predicate) {\n predicate = gate.scopePredicateById(\n syncOp.documentId,\n subject,\n syncOp.branch,\n signal,\n );\n predicates.set(key, predicate);\n }\n\n const readable = await predicate;\n if (!syncOp.scopes.some((scope) => readable(scope))) {\n held.add(syncOp.id);\n }\n }\n\n return held;\n}\n\n/**\n * Polls the switchboard for new sync envelopes and acknowledges previously\n * received operations.\n *\n * `forbiddenIds` and `heldOpIds` are two different refusals. A forbidden\n * document is consumed: its delivery counters are advanced as though it had\n * been sent, so it is never reconsidered. A held sync operation is withheld:\n * nothing about it is touched, so a policy that later widens serves it whole on\n * a subsequent poll. Which one applies is the caller's decision, and the two\n * are intersected, so a document refused either way is not served.\n *\n * Ordinal frames of reference:\n * - `outboxAck` / `outboxLatest`: switchboard's ordinals (used to trim/filter\n * the switchboard's outbox)\n * - `ackOrdinal` in the response: the pushing client's ordinals (highest\n * client ordinal the switchboard has successfully applied, so the client\n * can trim its own outbox)\n */\nexport function pollSyncEnvelopes(\n syncManager: ISyncManager,\n args: {\n channelId: string;\n outboxAck: number;\n outboxLatest: number;\n },\n forbiddenIds: ReadonlySet<string> = new Set(),\n heldOpIds: ReadonlySet<string> = new Set(),\n gatedOpIds?: ReadonlySet<string>,\n): {\n envelopes: any[];\n ackOrdinal: number;\n deadLetters: Array<{\n documentId: string;\n error: string;\n errorType: string;\n jobId: string;\n branch: string;\n scopes: string[];\n operationCount: number;\n }>;\n hasMore: boolean;\n} {\n // The gate ran against a snapshot taken before its first await, so an entry\n // the outbox gained while it was deciding carries no verdict. Serving one\n // would hand over a scope nobody authorized, so an entry the gate never saw\n // is held exactly like one it refused -- withheld, not consumed, which leaves\n // it in the outbox for the next poll to evaluate properly.\n const isHeld = (syncOp: SyncOperation): boolean =>\n heldOpIds.has(syncOp.id) ||\n (gatedOpIds !== undefined && !gatedOpIds.has(syncOp.id));\n\n let remote;\n try {\n remote = syncManager.getById(args.channelId);\n } catch (error) {\n throw new GraphQLError(\n `Channel not found: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // The subgraph's drive and binding checks run before this call, so reaching\n // here is an authorized poll: the only evidence the switchboard has that this\n // channel still has a holder.\n remote.channel.notePoll();\n\n // Dead-letter items can originate from failed inbox jobs whose documentId is\n // outside this channel's collection, so they are filtered by the caller's read\n // access independently of the outbox (see the poll resolver in subgraph.ts).\n const deadLetters = remote.channel.deadLetter.items\n .filter((syncOp) => !forbiddenIds.has(syncOp.documentId) && !isHeld(syncOp))\n .map((syncOp) => ({\n documentId: syncOp.documentId,\n error: syncOp.error?.message ?? \"Unknown error\",\n // Sent so a peer mirrors this replica's quarantine decision rather than\n // freezing a document it is deliberately still syncing.\n errorType: syncOperationErrorType(syncOp.error),\n jobId: syncOp.jobId,\n branch: syncOp.branch,\n scopes: syncOp.scopes,\n operationCount: syncOp.operations.length,\n }));\n\n // Trim acked outbox items, but only those we have fully emitted to this\n // client. Without the emittedCount guard, a syncOp queued behind a page cap\n // (never sent) would be dropped when ackOrdinal sweeps past its ordinals,\n // because ackOrdinal can be advanced by OTHER syncOps the client did\n // receive — same root-cause class as the resolver's per-op filter bug.\n if (args.outboxAck > 0) {\n const ackOrdinal = args.outboxAck;\n const outbox = remote.channel.outbox;\n const toRemove: SyncOperation[] = [];\n for (const syncOp of outbox.items) {\n const fullyEmitted =\n (syncOp.emittedCount ?? 0) >= syncOp.operations.length;\n if (!fullyEmitted) continue;\n let maxOrdinal = 0;\n for (const op of syncOp.operations) {\n if (op.context.ordinal > maxOrdinal) maxOrdinal = op.context.ordinal;\n }\n if (maxOrdinal <= ackOrdinal) {\n toRemove.push(syncOp);\n }\n }\n if (toRemove.length > 0) {\n for (const syncOp of toRemove) {\n syncOp.executed();\n }\n outbox.remove(...toRemove);\n }\n }\n\n const operations = remote.channel.outbox.items;\n\n // Drain forbidden operations: mark them fully delivered so the page loop's\n // `remaining.length === 0` guard skips them (never emitted to this caller) and\n // the ack trim above evicts them on a later poll. The caller proved they may\n // not read these documents, so advancing the cursor past them is correct and\n // avoids re-evaluating them every poll.\n if (forbiddenIds.size > 0) {\n for (const syncOp of operations) {\n if (forbiddenIds.has(syncOp.documentId)) {\n syncOp.deliveredCount = syncOp.operations.length;\n syncOp.emittedCount = syncOp.operations.length;\n }\n }\n }\n\n if (operations.length === 0) {\n return {\n envelopes: [],\n ackOrdinal: remote.channel.inbox.ackOrdinal,\n deadLetters,\n hasMore: false,\n };\n }\n\n // Dependencies point backward in ordinal order, so sorting by first op\n // ordinal preserves dependency ordering across the page.\n const sorted = [...operations].sort((a, b) => {\n const aOrdinal = a.operations[0]?.context.ordinal ?? 0;\n const bOrdinal = b.operations[0]?.context.ordinal ?? 0;\n return aOrdinal - bOrdinal;\n });\n\n const envelopes: SyncEnvelopeArg[] = [];\n let pageOps = 0;\n let hasMore = false;\n let maxOrdinal = args.outboxLatest;\n\n outer: for (const syncOp of sorted) {\n if (pageOps >= MAX_OPERATIONS_PER_PAGE) {\n hasMore = true;\n break;\n }\n\n // Before the delivery cursor is read or written, because holding must leave\n // no trace: the counters are what a later ack sweep consults to decide the\n // entry was delivered and may be evicted. A hold sets no hasMore either --\n // there is no later page that would serve it, so claiming one would spin the\n // puller.\n if (isHeld(syncOp)) continue;\n\n // Advance the per-syncOp delivery cursor past leading ops the client has\n // both received (outboxLatest) and we have previously emitted\n // (emittedCount). Gating on emittedCount prevents skipping ops that were\n // never sent because an earlier syncOp filled the page cap — a syncOp\n // queued behind that cap has emittedCount = 0 and stays un-advanced even\n // when outboxLatest sweeps past its ordinals. Gating on outboxLatest\n // (rather than emittedCount alone) keeps response-loss recovery: emitted\n // but unconfirmed ops re-emit on the next poll.\n syncOp.deliveredCount ??= 0;\n syncOp.emittedCount ??= 0;\n while (\n syncOp.deliveredCount < syncOp.emittedCount &&\n syncOp.operations[syncOp.deliveredCount].context.ordinal <=\n args.outboxLatest\n ) {\n syncOp.deliveredCount += 1;\n }\n\n const remaining = syncOp.operations.slice(syncOp.deliveredCount);\n if (remaining.length === 0) continue;\n\n let prevPartKey: string | undefined;\n let partIdx = 0;\n let i = 0;\n while (i < remaining.length) {\n if (pageOps >= MAX_OPERATIONS_PER_PAGE) {\n hasMore = true;\n break outer;\n }\n\n const remainingPage = MAX_OPERATIONS_PER_PAGE - pageOps;\n // Always emit at least one op so an oversized single op makes progress.\n const chunkSize = Math.max(\n 1,\n Math.min(\n MAX_OPERATIONS_PER_ENVELOPE,\n remainingPage,\n remaining.length - i,\n ),\n );\n const slice = remaining.slice(i, i + chunkSize);\n\n const isOnly =\n remaining.length <= MAX_OPERATIONS_PER_ENVELOPE &&\n remaining.length <= remainingPage;\n const baseKey = syncOp.jobId || undefined;\n const partKey = isOnly\n ? baseKey\n : baseKey\n ? `${baseKey}__p${partIdx}`\n : undefined;\n const partDeps =\n partIdx === 0\n ? syncOp.jobDependencies.filter(Boolean)\n : prevPartKey\n ? [prevPartKey]\n : [];\n\n for (const op of slice) {\n if (op.context.ordinal > maxOrdinal) maxOrdinal = op.context.ordinal;\n }\n\n envelopes.push({\n type: \"OPERATIONS\",\n channelMeta: { id: args.channelId },\n operations: slice.map((op) => ({\n operation: serializeOperationForGraphQL(op.operation),\n context: op.context,\n })),\n cursor: {\n remoteName: remote.meta.name,\n cursorOrdinal: 0,\n lastSyncedAtUtcMs: Date.now().toString(),\n },\n key: partKey,\n dependsOn: partDeps.length > 0 ? partDeps : undefined,\n });\n\n pageOps += slice.length;\n i += slice.length;\n prevPartKey = partKey;\n partIdx++;\n\n // Record how far through this syncOp we have emitted. The cursor advance\n // above only moves past ops counted here, so an unsent syncOp (e.g. one\n // that never reached emission because of the page cap) cannot have its\n // delivery cursor advanced by a future poll's outboxLatest.\n const emittedThrough = syncOp.deliveredCount + i;\n if (emittedThrough > syncOp.emittedCount) {\n syncOp.emittedCount = emittedThrough;\n }\n\n if (i < remaining.length && pageOps >= MAX_OPERATIONS_PER_PAGE) {\n hasMore = true;\n break outer;\n }\n }\n }\n\n for (const envelope of envelopes) {\n if (envelope.cursor) envelope.cursor.cursorOrdinal = maxOrdinal;\n }\n\n return {\n envelopes,\n ackOrdinal: remote.channel.inbox.ackOrdinal,\n deadLetters,\n hasMore,\n };\n}\n\ntype SyncEnvelopeArg = {\n type: string;\n channelMeta: { id: string };\n operations?: Array<{\n operation: any;\n context: {\n documentId: string;\n documentType: string;\n scope: string;\n branch: string;\n ordinal: number;\n };\n }> | null;\n cursor?: {\n remoteName: string;\n cursorOrdinal: number;\n lastSyncedAtUtcMs?: string | null;\n } | null;\n key?: string;\n dependsOn?: string[];\n};\n\n/**\n * Receives sync envelopes pushed by a client and adds them to the\n * appropriate channel inboxes.\n *\n * The `ordinal` in each operation's context is the client's local ordinal.\n * It must be preserved because the inbox mailbox tracks applied ordinals\n * and returns the highest one as `ackOrdinal` in pollSyncEnvelopes.\n */\nexport function pushSyncEnvelopes(\n syncManager: ISyncManager,\n args: {\n envelopes: SyncEnvelopeArg[];\n },\n): Promise<boolean> {\n type RemoteRef = ReturnType<ISyncManager[\"getById\"]>;\n const remoteSyncOps = new Map<RemoteRef, SyncOperation[]>();\n\n for (const envelope of args.envelopes) {\n let remote: RemoteRef;\n try {\n remote = syncManager.getById(envelope.channelMeta.id);\n } catch (error) {\n throw new GraphQLError(\n `Channel not found: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n if (!envelope.operations || envelope.operations.length === 0) {\n continue;\n }\n\n // A Manual-poll holder never polls on a schedule, so a push is the only\n // liveness it ever reports. It is stamped below the empty-envelope exit,\n // and after the caller's per-operation checks upstream: an envelope\n // carrying nothing is authorized by nothing, so it proves nothing.\n remote.channel.notePoll();\n\n const syncOps = envelopesToSyncOperations(\n envelope as Parameters<typeof envelopesToSyncOperations>[0],\n remote.meta.name,\n );\n\n if (!remoteSyncOps.has(remote)) {\n remoteSyncOps.set(remote, []);\n }\n remoteSyncOps.get(remote)!.push(...syncOps);\n }\n\n for (const [remote, syncOps] of remoteSyncOps) {\n const consolidated = consolidateSyncOperations(syncOps);\n\n const validKeys = new Set(\n consolidated.map((op) => op.jobId).filter(Boolean),\n );\n for (const syncOp of consolidated) {\n syncOp.jobDependencies = syncOp.jobDependencies.filter((dep) =>\n validKeys.has(dep),\n );\n }\n\n remote.channel.inbox.add(...consolidated);\n }\n\n return Promise.resolve(true);\n}\n","import { camelCase, kebabCase } from \"change-case\";\nimport {\n setName,\n type DocumentModelModule,\n} from \"@powerhousedao/shared/document-model\";\nimport { GraphQLError, Kind, parse } from \"graphql\";\nimport {\n generateDocumentModelSchema,\n getDocumentModelSchemaName,\n} from \"../utils/create-schema.js\";\nimport type { CanonicalDocumentId } from \"../services/authorization.service.js\";\nimport { BaseSubgraph } from \"./base-subgraph.js\";\nimport { toGqlPhDocument } from \"./reactor/adapters.js\";\nimport type {\n PhDocument,\n PhDocumentResultPage,\n} from \"./reactor/gen/graphql.js\";\nimport {\n createDocumentWithInitialState as createDocumentWithInitialStateResolver,\n createEmptyDocument as createEmptyDocumentResolver,\n documentIncomingRelationships as documentIncomingRelationshipsResolver,\n documentOutgoingRelationships as documentOutgoingRelationshipsResolver,\n document as documentResolver,\n findDocuments as findDocumentsResolver,\n} from \"./reactor/resolvers.js\";\nimport type { Context, SubgraphArgs } from \"./types.js\";\n\n/** A resolver function that lives inside a document-model subgraph. */\n\nexport type DocumentModelResolverFn = (...args: any[]) => unknown;\n\n/**\n * A resolver map for a single GraphQL type in a document-model subgraph.\n * Each key is a field name (or `__resolveType` for unions) and each value\n * is a resolver function.\n */\nexport type DocumentModelResolverMap = Record<string, DocumentModelResolverFn>;\n\n/** View filter shared across query resolvers. */\ntype ViewArg = { branch?: string; scopes?: string[] };\n\n/** Paging argument shared across query resolvers. */\ntype PagingArg = { limit?: number; offset?: number; cursor?: string };\n\n/**\n * Known query resolvers generated for every document model.\n * `TDocument` is the GQL representation of the document (defaults to `PhDocument`).\n */\nexport interface DocumentModelQueryResolvers<\n TDocument extends PhDocument = PhDocument,\n> {\n document: (\n parent: unknown,\n args: { identifier: string; view?: ViewArg },\n ctx: Context,\n ) => Promise<{ document: TDocument; childIds: string[] }>;\n documents: (\n parent: unknown,\n args: { paging?: PagingArg },\n ctx: Context,\n ) => Promise<{ items: TDocument[] }>;\n findDocuments: (\n parent: unknown,\n args: {\n search?: { parentId?: string; identifiers?: string[] } | null;\n view?: ViewArg;\n paging?: PagingArg;\n },\n ctx: Context,\n ) => Promise<PhDocumentResultPage>;\n documentOutgoingRelationships: (\n parent: unknown,\n args: {\n sourceIdentifier: string;\n relationshipType: string;\n view?: ViewArg;\n paging?: PagingArg;\n },\n ctx: Context,\n ) => Promise<PhDocumentResultPage>;\n documentIncomingRelationships: (\n parent: unknown,\n args: {\n targetIdentifier: string;\n relationshipType: string;\n view?: ViewArg;\n paging?: PagingArg;\n },\n ctx: Context,\n ) => Promise<PhDocumentResultPage>;\n}\n\n/**\n * Known mutation resolvers generated for every document model.\n * `TDocument` is the GQL representation of the document (defaults to `PhDocument`).\n * Operations specific to each model are captured by the index signature.\n */\nexport interface DocumentModelMutationResolvers<\n TDocument extends PhDocument = PhDocument,\n> {\n createDocument: (\n parent: unknown,\n args: {\n name: string;\n parentIdentifier?: string;\n slug?: string;\n preferredEditor?: string;\n initialState?: Record<string, Record<string, unknown>>;\n },\n ctx: Context,\n ) => Promise<TDocument>;\n createEmptyDocument: (\n parent: unknown,\n args: { parentIdentifier?: string },\n ctx: Context,\n ) => Promise<TDocument>;\n /** Dynamic operation resolvers (sync and async variants). */\n [operationName: string]: DocumentModelResolverFn;\n}\n\n/** The resolvers that a `DocumentModelSubgraph` exposes. */\nexport interface DocumentModelSubgraphResolvers<\n TDocument extends PhDocument = PhDocument,\n> {\n Query: DocumentModelResolverMap;\n Mutation: DocumentModelResolverMap;\n [namespaceKey: string]:\n | DocumentModelResolverMap\n | DocumentModelQueryResolvers<TDocument>\n | DocumentModelMutationResolvers<TDocument>;\n}\n\n/**\n * New document model subgraph that uses reactorClient instead of legacy reactor.\n * This class auto-generates GraphQL queries and mutations for a document model.\n */\nexport class DocumentModelSubgraph extends BaseSubgraph {\n declare resolvers: DocumentModelSubgraphResolvers;\n private documentModel: DocumentModelModule;\n\n constructor(documentModel: DocumentModelModule, args: SubgraphArgs) {\n super(args);\n this.documentModel = documentModel;\n this.name = kebabCase(documentModel.documentModel.global.name);\n this.typeDefs = generateDocumentModelSchema(\n this.documentModel.documentModel.global,\n { useNewApi: true },\n );\n this.resolvers = this.generateResolvers();\n }\n\n /** Returns the typed query resolvers for this document model. */\n get queryResolvers(): DocumentModelQueryResolvers {\n const documentName = getDocumentModelSchemaName(\n this.documentModel.documentModel.global,\n );\n return this.resolvers[\n `${documentName}Queries`\n ] as DocumentModelQueryResolvers;\n }\n\n /** Returns the typed mutation resolvers for this document model. */\n get mutationResolvers(): DocumentModelMutationResolvers {\n const documentName = getDocumentModelSchemaName(\n this.documentModel.documentModel.global,\n );\n return this.resolvers[\n `${documentName}Mutations`\n ] as DocumentModelMutationResolvers;\n }\n\n /** Drops the items the host's own ACL refuses the caller. */\n async #readableItems(\n page: PhDocumentResultPage,\n ctx: Context,\n ): Promise<PhDocumentResultPage> {\n if (this.authorizationService.isSupremeAdmin(ctx.user?.address)) {\n return page;\n }\n const items: PhDocument[] = [];\n for (const item of page.items) {\n if (await this.canReadDocument(item.id as CanonicalDocumentId, ctx)) {\n items.push(item);\n }\n }\n return { ...page, items };\n }\n\n /**\n * Generate __resolveType functions for union types found in the document model schema.\n * Parses the state schema to find union definitions and their member types,\n * then uses unique field presence to discriminate between member types at runtime.\n */\n private generateUnionResolvers(): Record<string, DocumentModelResolverMap> {\n const documentName = getDocumentModelSchemaName(\n this.documentModel.documentModel.global,\n );\n const specification =\n this.documentModel.documentModel.global.specifications.at(-1);\n if (!specification) return {};\n\n const globalSchema = specification.state.global.schema ?? \"\";\n const localSchema = specification.state.local.schema ?? \"\";\n const fullSchema = `${globalSchema}\\n${localSchema}`;\n\n if (!fullSchema.trim()) return {};\n\n let ast;\n try {\n ast = parse(fullSchema);\n } catch {\n return {};\n }\n\n // Build map: object type name -> field names\n const objectFieldsMap = new Map<string, string[]>();\n for (const def of ast.definitions) {\n if (def.kind === Kind.OBJECT_TYPE_DEFINITION) {\n objectFieldsMap.set(\n def.name.value,\n def.fields?.map((f) => f.name.value) ?? [],\n );\n }\n }\n\n const resolvers: Record<string, DocumentModelResolverMap> = {};\n\n for (const def of ast.definitions) {\n if (def.kind !== Kind.UNION_TYPE_DEFINITION) continue;\n\n const unionName = def.name.value;\n const memberTypes = def.types?.map((t) => t.name.value) ?? [];\n if (memberTypes.length === 0) continue;\n\n // Compute unique fields per member type\n const uniqueFields: Record<string, string[]> = {};\n for (const memberType of memberTypes) {\n const ownFields = objectFieldsMap.get(memberType) ?? [];\n const otherFields = new Set(\n memberTypes\n .filter((t) => t !== memberType)\n .flatMap((t) => objectFieldsMap.get(t) ?? []),\n );\n uniqueFields[memberType] = ownFields.filter((f) => !otherFields.has(f));\n }\n\n const prefixedUnionName = `${documentName}_${unionName}`;\n\n resolvers[prefixedUnionName] = {\n __resolveType: (obj: Record<string, unknown>) => {\n for (const memberType of memberTypes) {\n const fields = uniqueFields[memberType] ?? [];\n if (fields.length > 0 && fields.some((f) => f in obj)) {\n return `${documentName}_${memberType}`;\n }\n }\n return `${documentName}_${memberTypes[0]}`;\n },\n };\n }\n\n return resolvers;\n }\n\n /**\n * Generate resolvers for this document model using reactorClient\n * Uses flat queries (not nested) consistent with ReactorSubgraph patterns\n */\n private generateResolvers(): DocumentModelSubgraphResolvers {\n const documentType = this.documentModel.documentModel.global.id;\n const documentName = getDocumentModelSchemaName(\n this.documentModel.documentModel.global,\n );\n const operations =\n this.documentModel.documentModel.global.specifications\n .at(-1)\n ?.modules.flatMap((module) =>\n module.operations.filter((op) => op.name),\n ) ?? [];\n\n return {\n ...this.generateUnionResolvers(),\n Query: {\n // Namespace resolver: returns empty object so nested field resolvers can run\n [documentName]: () => ({}),\n },\n [`${documentName}Queries`]: {\n // Get a specific document by identifier\n document: async (\n _: unknown,\n args: {\n identifier: string;\n view?: { branch?: string; scopes?: string[] };\n },\n ctx: Context,\n ) => {\n const { identifier, view } = args;\n\n if (!identifier) {\n throw new GraphQLError(\"Document identifier is required\");\n }\n\n const result = await documentResolver(\n this.reactorClient,\n { identifier, view },\n this.viewSubject(ctx),\n );\n\n if (result.document.documentType !== documentType) {\n throw new GraphQLError(\n `Document with id ${identifier} is not of type ${documentType}`,\n );\n }\n\n await this.assertCanReadCanonical(\n result.document.id as CanonicalDocumentId,\n ctx,\n );\n\n return result;\n },\n // Flat query: Get all documents of this type (paged)\n documents: async (\n _: unknown,\n args: {\n paging?: { limit?: number; offset?: number; cursor?: string };\n },\n ctx: Context,\n ) => {\n const { paging } = args;\n\n const result = await findDocumentsResolver(\n this.reactorClient,\n { search: { type: documentType }, paging },\n this.viewSubject(ctx),\n );\n\n return this.#readableItems(result, ctx);\n },\n // Flat query: Find documents by search criteria (type is built-in)\n // Uses shared findDocumentsResolver from reactor/resolvers.ts\n findDocuments: async (\n _: unknown,\n args: {\n search?: { parentId?: string; identifiers?: string[] } | null;\n view?: { branch?: string; scopes?: string[] };\n paging?: { limit?: number; offset?: number; cursor?: string };\n },\n ctx: Context,\n ) => {\n const { search, view, paging } = args;\n\n const result = await findDocumentsResolver(\n this.reactorClient,\n {\n search: { type: documentType, parentId: search?.parentId },\n view,\n paging,\n },\n this.viewSubject(ctx),\n );\n\n return this.#readableItems(result, ctx);\n },\n\n documentOutgoingRelationships: async (\n _: unknown,\n args: {\n sourceIdentifier: string;\n relationshipType: string;\n view?: { branch?: string; scopes?: string[] };\n paging?: { limit?: number; offset?: number; cursor?: string };\n },\n ctx: Context,\n ) => {\n const { relationshipType, view, paging } = args;\n\n const handle = await this.assertCanRead(args.sourceIdentifier, ctx);\n\n const result = await documentOutgoingRelationshipsResolver(\n this.reactorClient,\n {\n sourceIdentifier: handle.fetchIdentifier,\n relationshipType,\n view,\n paging,\n },\n this.viewSubject(ctx),\n );\n\n const readable = await this.#readableItems(result, ctx);\n const filteredItems = readable.items.filter(\n (item: PhDocument) => item.documentType === documentType,\n );\n\n return { ...readable, items: filteredItems };\n },\n\n documentIncomingRelationships: async (\n _: unknown,\n args: {\n targetIdentifier: string;\n relationshipType: string;\n view?: { branch?: string; scopes?: string[] };\n paging?: { limit?: number; offset?: number; cursor?: string };\n },\n ctx: Context,\n ) => {\n const { relationshipType, view, paging } = args;\n\n const handle = await this.assertCanRead(args.targetIdentifier, ctx);\n\n const result = await documentIncomingRelationshipsResolver(\n this.reactorClient,\n {\n targetIdentifier: handle.fetchIdentifier,\n relationshipType,\n view,\n paging,\n },\n this.viewSubject(ctx),\n );\n\n return this.#readableItems(result, ctx);\n },\n },\n Mutation: {\n // Namespace resolver: returns empty object so nested field resolvers can run\n [documentName]: () => ({}),\n },\n [`${documentName}Mutations`]: {\n createDocument: async (\n _: unknown,\n args: {\n name: string;\n parentIdentifier?: string;\n slug?: string;\n preferredEditor?: string;\n initialState?: Record<string, Record<string, unknown>>;\n },\n ctx: Context,\n ) => {\n const { name, slug, preferredEditor, initialState } = args;\n\n let parentIdentifier = args.parentIdentifier;\n if (parentIdentifier) {\n const handle = await this.assertCanWrite(parentIdentifier, ctx);\n parentIdentifier = handle.fetchIdentifier;\n } else {\n this.assertCanCreate(ctx);\n }\n\n let createdDoc;\n if (initialState || preferredEditor) {\n createdDoc = await createDocumentWithInitialStateResolver(\n this.reactorClient,\n {\n documentType,\n parentIdentifier,\n name,\n slug,\n preferredEditor,\n initialState: initialState ?? {},\n },\n this.graphqlManager.reactorDriveClient,\n this.viewSubject(ctx),\n );\n } else {\n createdDoc = await createEmptyDocumentResolver(\n this.reactorClient,\n {\n documentType,\n parentIdentifier,\n name,\n },\n this.graphqlManager.reactorDriveClient,\n this.viewSubject(ctx),\n );\n }\n\n // Auto-ownership: set creator as document owner\n if (ctx.user?.address && createdDoc?.id) {\n await this.documentPermissionService?.initializeDocumentProtection(\n createdDoc.id,\n ctx.user.address,\n this.authorizationService.config.defaultProtection,\n );\n }\n\n // Name fallback via SET_NAME (only for non-initialState path,\n // since initialState path sets name on header before creation)\n if (\n !initialState &&\n !preferredEditor &&\n name &&\n createdDoc.name !== name\n ) {\n const updatedDoc = await this.reactorClient.execute(\n createdDoc.id,\n \"main\",\n [setName(name)],\n undefined,\n this.viewSubject(ctx),\n );\n return toGqlPhDocument(updatedDoc);\n }\n\n return createdDoc;\n },\n createEmptyDocument: async (\n _: unknown,\n args: { parentIdentifier?: string },\n ctx: Context,\n ) => {\n let parentIdentifier = args.parentIdentifier;\n if (parentIdentifier) {\n const handle = await this.assertCanWrite(parentIdentifier, ctx);\n parentIdentifier = handle.fetchIdentifier;\n } else {\n this.assertCanCreate(ctx);\n }\n\n const result = await createEmptyDocumentResolver(\n this.reactorClient,\n {\n documentType,\n parentIdentifier,\n },\n this.graphqlManager.reactorDriveClient,\n this.viewSubject(ctx),\n );\n\n // Auto-ownership: set creator as document owner\n if (ctx.user?.address && result?.id) {\n await this.documentPermissionService?.initializeDocumentProtection(\n result.id,\n ctx.user.address,\n this.authorizationService.config.defaultProtection,\n );\n }\n\n return result;\n },\n // Generate sync and async mutations for each operation\n ...operations.reduce((mutations, op) => {\n // Sync mutation\n mutations[camelCase(op.name!)] = async (\n _: unknown,\n args: { docId: string; input: unknown },\n ctx: Context,\n ) => {\n const { docId, input } = args;\n\n const handle = await this.assertCanExecuteOperation(\n docId,\n op.name!,\n ctx,\n );\n const effectiveDocId = handle.fetchIdentifier;\n\n const doc = await this.reactorClient.get(effectiveDocId, {\n subject: this.viewSubject(ctx),\n });\n if (doc.header.documentType !== documentType) {\n throw new GraphQLError(\n `Document with id ${docId} is not of type ${documentType}`,\n );\n }\n\n const action = this.documentModel.actions[camelCase(op.name!)];\n if (!action) {\n throw new GraphQLError(`Action ${op.name} not found`);\n }\n\n try {\n const updatedDoc = await this.reactorClient.execute(\n effectiveDocId,\n \"main\",\n [action(input)],\n undefined,\n this.viewSubject(ctx),\n );\n return toGqlPhDocument(updatedDoc);\n } catch (error) {\n throw new GraphQLError(\n error instanceof Error ? error.message : `Failed to ${op.name}`,\n );\n }\n };\n\n // Async mutation - returns job ID\n mutations[`${camelCase(op.name!)}Async`] = async (\n _: unknown,\n args: { docId: string; input: unknown },\n ctx: Context,\n ) => {\n const { docId, input } = args;\n\n const handle = await this.assertCanExecuteOperation(\n docId,\n op.name!,\n ctx,\n );\n const effectiveDocId = handle.fetchIdentifier;\n\n const doc = await this.reactorClient.get(effectiveDocId, {\n subject: this.viewSubject(ctx),\n });\n if (doc.header.documentType !== documentType) {\n throw new GraphQLError(\n `Document with id ${docId} is not of type ${documentType}`,\n );\n }\n\n const action = this.documentModel.actions[camelCase(op.name!)];\n if (!action) {\n throw new GraphQLError(`Action ${op.name} not found`);\n }\n\n try {\n const jobInfo = await this.reactorClient.executeAsync(\n effectiveDocId,\n \"main\",\n [action(input)],\n );\n return jobInfo.id;\n } catch (error) {\n throw new GraphQLError(\n error instanceof Error ? error.message : `Failed to ${op.name}`,\n );\n }\n };\n\n return mutations;\n }, {} as DocumentModelResolverMap),\n },\n };\n }\n}\n","import type { DriveOwnershipCache } from \"./drive-ownership-cache.js\";\nimport type { FetchHandler } from \"./types.js\";\n\nexport type DriveFetchMiddleware = (handler: FetchHandler) => FetchHandler;\n\nconst DRIVE_ID_HEADER = \"drive-id\";\n\n/**\n * Operations that legitimately run before the target drive exists in the\n * cache. Drive creation is the obvious case (a brand-new drive cannot be\n * in the ownership set yet); other create-shaped operations that may\n * synthesize a drive must be added here too.\n */\nconst CACHE_BYPASS_OPERATIONS = new Set([\n \"createDocument\",\n \"createEmptyDocument\",\n]);\n\nconst driveIdMap = new WeakMap<globalThis.Request, string>();\n\n/** Internal — only `graphql-manager.ts` should call this. */\nexport function getRequestDriveId(\n request: globalThis.Request,\n): string | undefined {\n return driveIdMap.get(request);\n}\n\n/**\n * Returns a fetch middleware that validates the `Drive-Id` header against\n * the in-memory ownership cache. Layout:\n *\n * - No header → pass through. The LB has already round-robined; nothing\n * to validate here.\n * - Header present and drive in cache → record on the request map (for\n * the context factory to read into `context.driveId`) and pass through.\n * - Header present, drive missing, but the operation is `createDocument`\n * or `createEmptyDocument` → pass through. The drive may be in the\n * process of being created.\n * - Otherwise → return `421 Misdirected Request` with a structured body.\n * The client (or LB) can surface this as a wrong-shard signal.\n */\nexport function createDriveFetchMiddleware(\n cache: DriveOwnershipCache,\n): DriveFetchMiddleware {\n return (next: FetchHandler): FetchHandler =>\n async (request: globalThis.Request): Promise<globalThis.Response> => {\n const driveId = request.headers.get(DRIVE_ID_HEADER) ?? \"\";\n if (driveId === \"\") {\n return next(request);\n }\n\n if (cache.has(driveId)) {\n driveIdMap.set(request, driveId);\n return next(request);\n }\n\n if (await isCacheBypassOperation(request)) {\n return next(request);\n }\n\n return wrongShardResponse(driveId);\n };\n}\n\nasync function isCacheBypassOperation(\n request: globalThis.Request,\n): Promise<boolean> {\n if (request.method !== \"POST\") {\n return false;\n }\n try {\n const body = (await request.clone().json()) as {\n operationName?: unknown;\n query?: unknown;\n };\n if (typeof body.operationName === \"string\") {\n return CACHE_BYPASS_OPERATIONS.has(body.operationName);\n }\n if (typeof body.query === \"string\") {\n return CACHE_BYPASS_OPERATIONS.has(extractOperationName(body.query));\n }\n return false;\n } catch {\n return false;\n }\n}\n\nconst OPERATION_NAME_PATTERN = /\\b(?:mutation|query|subscription)\\s+(\\w+)/;\n\nfunction extractOperationName(query: string): string {\n const match = OPERATION_NAME_PATTERN.exec(query);\n return match ? match[1] : \"\";\n}\n\nfunction wrongShardResponse(driveId: string): globalThis.Response {\n return new globalThis.Response(\n JSON.stringify({ error: \"wrong-shard\", driveId }),\n {\n status: 421,\n headers: { \"content-type\": \"application/json\" },\n },\n );\n}\n","import {\n DEFAULT_DRIVE_CONTAINER_TYPES,\n type IReactorClient,\n} from \"@powerhousedao/reactor\";\n\n/**\n * In-memory record of which drives this switchboard instance owns.\n *\n * Populated at startup by walking the reactor for documents whose type is\n * listed in `DEFAULT_DRIVE_CONTAINER_TYPES` (both legacy `document-drive`\n * and `reactor-drive`). Mutated explicitly by resolver hooks after\n * successful drive create / delete operations. Read by the drive-validation\n * fetch middleware to short-circuit wrong-shard requests with a structured\n * 421 response.\n */\nexport class DriveOwnershipCache {\n private readonly drives = new Set<string>();\n\n constructor(private readonly reactorClient: IReactorClient) {}\n\n async init(): Promise<void> {\n this.drives.clear();\n for (const driveType of DEFAULT_DRIVE_CONTAINER_TYPES) {\n let page = await this.reactorClient.find({ type: driveType });\n while (true) {\n for (const drive of page.results) {\n this.drives.add(drive.header.id);\n }\n if (!page.next) {\n break;\n }\n page = await page.next();\n }\n }\n }\n\n has(driveId: string): boolean {\n return this.drives.has(driveId);\n }\n\n add(driveId: string): void {\n this.drives.add(driveId);\n }\n\n remove(driveId: string): void {\n this.drives.delete(driveId);\n }\n\n size(): number {\n return this.drives.size;\n }\n}\n","import type { GraphQLSchema } from \"graphql\";\nimport type { Request as SSERequest } from \"graphql-sse\";\nimport { createHandler } from \"graphql-sse/lib/use/fetch\";\nimport type { Context } from \"./types.js\";\n\n/**\n * Options for creating the GraphQL-over-SSE handler.\n */\nexport interface SSEHandlerOptions {\n schema: GraphQLSchema;\n /**\n * Build a GraphQL context from the incoming Fetch API Request.\n * Called once per subscription (not per event).\n *\n * The request has already passed through auth middleware by the time\n * this is invoked, so getAuthContext(request) will return the populated\n * AuthContext from the WeakMap.\n */\n contextFactory: (req: Request) => Promise<Context> | Context;\n}\n\n/**\n * Create a Fetch-API-compatible SSE handler for GraphQL subscriptions\n * using the graphql-sse library (graphql-sse protocol).\n *\n * This runs alongside the existing WebSocket (graphql-ws) transport\n * so clients can choose either protocol.\n *\n * The returned handler is a standard FetchHandler: (req: Request) => Promise<Response>.\n * It can be mounted via httpAdapter.mount() like any other handler, and auth\n * flows through the WeakMap pattern (authFetchMiddleware populates the context\n * before this handler is called).\n *\n * Clients connect via \"distinct connections mode\" (POST with\n * `Accept: text/event-stream`). Single-connection mode is disabled\n * because it adds token-management complexity with no benefit here.\n */\nexport function createGraphQLSSEHandler(\n options: SSEHandlerOptions,\n): (req: Request) => Promise<Response> {\n const { schema, contextFactory } = options;\n\n return createHandler<Context>({\n schema,\n // Returning null disables single-connection mode. All clients use\n // \"distinct connections mode\" (one POST per subscription).\n // Auth is handled upstream by authFetchMiddleware.\n authenticate: () => null,\n context: (req: SSERequest<Request>) => contextFactory(req.raw),\n });\n}\n","import type { IAnalyticsStore } from \"@powerhousedao/analytics-engine-core\";\nimport type {\n IDriveClient,\n IReactorClient,\n IRelationalDb,\n ISyncManager,\n SyncScopeGate,\n} from \"@powerhousedao/reactor\";\nimport type {\n Context,\n ISubgraph,\n SubgraphClass,\n} from \"@powerhousedao/reactor-api\";\nimport type { DocumentDriveDocument } from \"@powerhousedao/shared/document-drive\";\nimport type { DocumentModelModule } from \"@powerhousedao/shared/document-model\";\nimport type { ILogger } from \"document-model\";\nimport type { GraphQLSchema } from \"graphql\";\nimport type { IncomingHttpHeaders } from \"http\";\nimport type http from \"node:http\";\nimport path from \"node:path\";\nimport { match } from \"path-to-regexp\";\nimport type { WebSocketServer } from \"ws\";\nimport {\n CORE_PACKAGE_NAME,\n HttpRouteService,\n type IHttpScope,\n} from \"../http/index.js\";\nimport { debounce } from \"../packages/util.js\";\nimport type { AuthService, User } from \"../services/auth.service.js\";\nimport type {\n CanonicalDocumentId,\n IAuthorizationService,\n} from \"../services/authorization.service.js\";\nimport type { DocumentPermissionService } from \"../services/document-permission.service.js\";\nimport {\n buildSubgraphSchemaModule,\n createMergedSchema,\n createSchema,\n} from \"../utils/create-schema.js\";\nimport { callerSubject } from \"./base-subgraph.js\";\nimport { DocumentModelSubgraph } from \"./document-model-subgraph.js\";\nimport {\n getAuthContext,\n type AuthFetchMiddleware,\n} from \"./gateway/auth-middleware.js\";\nimport {\n createDriveFetchMiddleware,\n getRequestDriveId,\n type DriveFetchMiddleware,\n} from \"./gateway/drive-middleware.js\";\nimport { DriveOwnershipCache } from \"./gateway/drive-ownership-cache.js\";\nimport type { RequireAuthFetchMiddleware } from \"./gateway/require-auth-middleware.js\";\nimport {\n WS_CLOSE_REASON_AUTHENTICATION_REQUIRED,\n WS_CLOSE_REASON_BEARER_REJECTED,\n type FetchHandler,\n type GatewayContextFactory,\n type IGatewayAdapter,\n type IHttpAdapter,\n type AdapterRouteHandle,\n type SubgraphDefinition,\n type WsConnection,\n type WsDisposer,\n type WsHandlers,\n} from \"./gateway/types.js\";\nimport { createGraphQLSSEHandler } from \"./sse.js\";\n\nconst DOCUMENT_MODELS_TO_EXCLUDE: string[] = [];\n\n/**\n * Check if a document model has any operations with valid schemas.\n * Document models without valid operation schemas cannot generate valid subgraph schemas.\n */\nfunction hasOperationSchemas(documentModel: DocumentModelModule): boolean {\n const specification =\n documentModel.documentModel.global.specifications.at(-1);\n if (!specification) return false;\n const hasValidSchema = (schema: string | null | undefined) =>\n schema && /\\b(input|type|enum|union|interface)\\s+\\w+/.test(schema);\n return specification.modules.some((module) =>\n module.operations.some((op) => hasValidSchema(op.schema)),\n );\n}\n\n/**\n * Filter document models to keep only the latest version of each unique document model.\n */\nfunction filterLatestDocumentModelVersions(\n documentModels: DocumentModelModule[],\n): DocumentModelModule[] {\n const latestByName = new Map<string, DocumentModelModule>();\n\n for (const documentModel of documentModels) {\n const name = documentModel.documentModel.global.name;\n const existing = latestByName.get(name);\n\n if (!existing) {\n latestByName.set(name, documentModel);\n continue;\n }\n\n const currentVersion =\n documentModel.documentModel.global.specifications.at(-1)?.version ?? 0;\n const existingVersion =\n existing.documentModel.global.specifications.at(-1)?.version ?? 0;\n\n if (currentVersion > existingVersion) {\n latestByName.set(name, documentModel);\n }\n }\n\n return Array.from(latestByName.values());\n}\n\nconst DefaultFeatureFlags = {\n enableDocumentModelSubgraphs: true,\n};\n\nexport type GraphqlManagerFeatureFlags = {\n enableDocumentModelSubgraphs?: boolean;\n};\n\n/**\n * The registration-source label for document-model-generated subgraphs, so\n * they can be pruned like package-contributed ones (see\n * regenerateDocumentModelSubgraphs).\n */\nconst DOCUMENT_MODEL_SUBGRAPH_SOURCE = \"document-models\";\n\n// Returning `false` closes 4403 with the reason `Forbidden`, so every refusal\n// looks alike and a client cannot tell \"sign in\" from \"that token is no good\".\n\n// An explicit close wins over the one graphql-ws would send, and carries a\n// reason. Under `graphql-ws/use/ws` the connection is `ctx.extra`, whose\n// `socket` is the `ws` WebSocket; narrowed here so the adapters keep passing a\n// plain object through.\nfunction refuseConnection(connection: WsConnection, reason: string): false {\n const { socket } = connection as {\n socket?: { close?: (code: number, reason: string) => void };\n };\n socket?.close?.(4403, reason);\n return false;\n}\n\n// The two halves of WebSocket auth: who is connected, and whether at all.\n\n// graphql-ws calls `context` per operation and `onConnect` once per connection.\n\n// A throw from `context` closes 4500, which clients treat as fatal; 4403 retries.\n\n// So every refusal happens in `onConnect`, and `context` only reads the verdict.\n\n// Admission matches HTTP: a bad bearer is refused, an absent one is no user.\n\n// Anonymous is refused only under REQUIRE_AUTHENTICATED_CALLER, as for fetch.\n\n// WS needs its own check: `ws` owns the upgrade, so the fetch chain never runs.\n\n// Admitted anonymous connections authorize per document, as they do over SSE.\nexport function createWsAuthHandlers(opts: {\n authService?: AuthService;\n /** Whether anonymous callers are refused; read at call time, not at build time. */\n requireAuthenticatedCaller: () => boolean;\n logger: ILogger;\n buildContext: (\n connectionParams: Record<string, unknown>,\n user?: User,\n ) => Context;\n}): WsHandlers<Context> {\n const resolved = new WeakMap<WsConnection, User | undefined>();\n\n return {\n onConnect: async (connectionParams, connection) => {\n let user: User | null = null;\n\n if (opts.authService) {\n try {\n user =\n await opts.authService.authenticateWebSocketConnection(\n connectionParams,\n );\n } catch (error) {\n // `warn`: the caller sent a bad token, the server is fine.\n opts.logger.warn(\n \"Refusing WebSocket connection: @error\",\n error instanceof Error ? error.message : error,\n );\n return refuseConnection(connection, WS_CLOSE_REASON_BEARER_REJECTED);\n }\n }\n\n if (user === null && opts.requireAuthenticatedCaller()) {\n opts.logger.warn(\n \"Refusing anonymous WebSocket connection: an authenticated caller is required\",\n );\n return refuseConnection(\n connection,\n WS_CLOSE_REASON_AUTHENTICATION_REQUIRED,\n );\n }\n\n resolved.set(connection, user ?? undefined);\n return true;\n },\n\n context: (connectionParams, connection) =>\n Promise.resolve(\n opts.buildContext(connectionParams, resolved.get(connection)),\n ),\n };\n}\n\nexport class GraphQLManager {\n private initialized = false;\n private coreSubgraphsMap = new Map<string, ISubgraph[]>();\n private contextFields: Record<string, any> = {};\n private readonly subgraphs = new Map<string, ISubgraph[]>();\n\n private readonly subgraphWsDisposers = new Map<string, WsDisposer>();\n #authMiddleware: AuthFetchMiddleware | undefined;\n #requireAuthMiddleware: RequireAuthFetchMiddleware | undefined;\n #driveMiddleware: DriveFetchMiddleware | undefined;\n readonly driveOwnershipCache: DriveOwnershipCache;\n\n /** Cached document models for schema generation - updated on init and regenerate */\n private cachedDocumentModels: DocumentModelModule[] = [];\n\n private readonly subgraphHandlerCache = new Map<\n string,\n { handler: FetchHandler; subgraph: ISubgraph }\n >();\n\n /** subgraphPath → the http adapter handle of its mounted route. */\n private readonly subgraphRouteHandles = new Map<string, AdapterRouteHandle>();\n\n /** Mounted SSE routes, keyed by path: the supergraph's and each subgraph's. */\n private readonly sseRouteHandles = new Map<string, AdapterRouteHandle>();\n\n /**\n * Package name → the subgraph instances registered from it, keyed by\n * subgraph name. Tracks the package association so that removed packages\n * can be torn down (see unregisterPackage / prunePackageSubgraphs).\n */\n private readonly packageSubgraphs = new Map<string, Map<string, ISubgraph>>();\n\n /** Per-subgraph handlers by name, before auth/drive middleware is applied,\n * for in-process queries by trusted internals. */\n readonly #internalSubgraphHandlers = new Map<\n string,\n { subgraph: ISubgraph; path: string; handler: FetchHandler }\n >();\n\n /**\n * Optional reactor-drive client. When the switchboard is configured with a\n * reactor-drive container, this is provided and the resolvers dispatch to\n * it for reactor-drive parents.\n */\n readonly reactorDriveClient?: IDriveClient;\n private readonly authorizationService: IAuthorizationService;\n /** Route service in use: the injected one, or one built on first need. */\n #fallbackRoutes: HttpRouteService | undefined;\n\n constructor(\n private readonly path: string,\n private readonly httpServer: http.Server,\n private readonly wsServer: WebSocketServer,\n private readonly reactorClient: IReactorClient,\n private readonly relationalDb: IRelationalDb,\n private readonly analyticsStore: IAnalyticsStore,\n private readonly syncManager: ISyncManager,\n private readonly logger: ILogger,\n private readonly httpAdapter: IHttpAdapter,\n private readonly gatewayAdapter: IGatewayAdapter<Context>,\n private readonly authService?: AuthService,\n private readonly documentPermissionService?: DocumentPermissionService,\n private readonly featureFlags: GraphqlManagerFeatureFlags = DefaultFeatureFlags,\n private readonly port: number = 4001,\n authorizationService?: IAuthorizationService,\n reactorDriveClient?: IDriveClient,\n private readonly syncServingGate?: SyncScopeGate,\n private readonly httpRoutes?: HttpRouteService,\n ) {\n if (!authorizationService) {\n throw new Error(\"GraphQLManager requires an authorizationService\");\n }\n this.authorizationService = authorizationService;\n this.reactorDriveClient = reactorDriveClient;\n\n this.driveOwnershipCache = new DriveOwnershipCache(this.reactorClient);\n\n // Each subscription-enabled subgraph adds listeners to the shared wsServer\n // via graphql-ws's useServer(). The handler cache bounds the count, so\n // unlimited is safe here.\n this.wsServer.setMaxListeners(0);\n }\n\n async init(\n coreSubgraphs: SubgraphClass[],\n authMiddleware?: AuthFetchMiddleware,\n requireAuthMiddleware?: RequireAuthFetchMiddleware,\n ) {\n this.#authMiddleware = authMiddleware;\n this.#requireAuthMiddleware = requireAuthMiddleware;\n this.logger.debug(`Initializing Subgraph Manager...`);\n\n await this.driveOwnershipCache.init();\n this.#driveMiddleware = createDriveFetchMiddleware(\n this.driveOwnershipCache,\n );\n this.logger.debug(\n `Drive ownership cache populated with ${this.driveOwnershipCache.size()} drives`,\n );\n\n // check if Document Drive model is available\n const modulesResult = await this.reactorClient.getDocumentModelModules();\n const models = modulesResult.results;\n\n // Cache models for schema generation\n this.cachedDocumentModels = models;\n\n const driveModel = models.find(\n (it: DocumentModelModule) =>\n it.documentModel.global.name === \"DocumentDrive\",\n );\n if (!driveModel) {\n throw new Error(\"DocumentDrive model required\");\n }\n\n await this.gatewayAdapter.start(this.httpServer);\n\n this.httpAdapter.setupMiddleware({ bodyLimit: \"50mb\" });\n\n // Register REST endpoint for drive info as a framework-agnostic FetchHandler.\n // posix.join, not join: these are URL routes, and on Windows path.join\n // would emit backslashes, mounting the route at \"\\d\\:drive\" so every\n // request 404s.\n const driveRoutePath = path.posix.join(this.path, \"d/:drive\");\n const driveMatcher = match<{ drive: string }>(driveRoutePath);\n const driveInfoHandler = async (request: Request): Promise<Response> => {\n const url = new URL(request.url);\n const matched = driveMatcher(url.pathname);\n const driveIdOrSlug = matched ? matched.params.drive : undefined;\n\n if (!driveIdOrSlug) {\n return Response.json(\n { error: \"Drive ID or slug is required\" },\n { status: 400 },\n );\n }\n\n const user = getAuthContext(request)?.user;\n try {\n // Read as the caller, so a drive whose domain it may not read serves\n // its header alone; discovery must still reach graphqlEndpoint.\n const driveDoc = await this.reactorClient.get<DocumentDriveDocument>(\n driveIdOrSlug,\n { subject: callerSubject(user) },\n );\n\n // Drive metadata is a document read, so it answers to the same\n // authorization as every GraphQL read (`assertCanReadCanonical`).\n // 404 rather than 403: a caller who may not read the drive must not\n // be able to tell \"protected\" from \"does not exist\" by probing slugs.\n const canRead = await this.authorizationService.canRead(\n driveDoc.header.id as CanonicalDocumentId,\n user?.address,\n );\n if (!canRead) {\n this.logger.debug(`Drive read refused: ${driveIdOrSlug}`);\n return Response.json({ error: \"Drive not found\" }, { status: 404 });\n }\n\n const forwardedProto = request.headers\n .get(\"x-forwarded-proto\")\n ?.split(\",\")[0]\n .trim();\n const protocol =\n (forwardedProto ?? url.protocol.replace(\":\", \"\")) + \":\";\n const forwardedHost = request.headers\n .get(\"x-forwarded-host\")\n ?.split(\",\")[0]\n .trim();\n const host = forwardedHost ?? request.headers.get(\"host\") ?? \"\";\n const forwardedPrefix =\n request.headers\n .get(\"x-forwarded-prefix\")\n ?.split(\",\")[0]\n .trim()\n .replace(/\\/$/, \"\") ?? \"\";\n const localBase = this.path === \"/\" ? \"\" : this.path;\n const basePath = forwardedPrefix + localBase;\n const graphqlEndpoint = `${protocol}//${host}${basePath}/graphql/r`;\n\n // Absent when the gate stripped it.\n const global = (driveDoc.state as Partial<typeof driveDoc.state>)\n .global;\n return Response.json({\n id: driveDoc.header.id,\n slug: driveDoc.header.slug,\n meta: driveDoc.header.meta,\n name: global?.name || driveDoc.header.name,\n icon: global?.icon ?? undefined,\n ...(graphqlEndpoint && { graphqlEndpoint }),\n });\n } catch (error: unknown) {\n this.logger.debug(`Drive not found: ${driveIdOrSlug}`, error);\n return Response.json({ error: \"Drive not found\" }, { status: 404 });\n }\n };\n\n // Identity resolution only — deliberately not the full\n // `#composeFetchMiddleware` chain. Drive discovery is the one read a\n // client makes before it can authenticate anything: Connect reads\n // `graphqlEndpoint` from here to register the sync remote, so a blanket\n // require-auth gate would leave an anonymous caller unable to ever reach\n // the authenticated surface. The bearer is read when present (an invalid\n // one is still a 401 from the auth middleware) and the drive is then\n // authorized individually, above. The drive-shard middleware is skipped\n // too: any healthy backend can answer this route.\n this.httpAdapter.mount(\n driveRoutePath,\n this.#authMiddleware\n ? this.#authMiddleware(driveInfoHandler)\n : driveInfoHandler,\n );\n this.logger.info(`Registered REST endpoint: GET ${driveRoutePath}`);\n\n await this.#setupCoreSubgraphs(\"graphql\", coreSubgraphs);\n\n if (this.featureFlags.enableDocumentModelSubgraphs) {\n await this.#setupDocumentModelSubgraphs(\"graphql\", models);\n }\n\n await this.#createSupergraphGateway();\n\n return this.updateRouter();\n }\n\n /**\n * Regenerate document model subgraphs when models are dynamically loaded.\n * Fetches current modules from reactor client (source of truth).\n */\n async regenerateDocumentModelSubgraphs(): Promise<void> {\n if (!this.featureFlags.enableDocumentModelSubgraphs) {\n return;\n }\n\n try {\n const modulesResult = await this.reactorClient.getDocumentModelModules();\n const models = modulesResult.results;\n\n // Update cached models for schema generation\n this.cachedDocumentModels = models;\n\n const registeredNames = await this.#setupDocumentModelSubgraphs(\n \"graphql\",\n models,\n );\n // A model removed since the last regeneration (e.g. its package was\n // uninstalled) must lose its subgraph; replacing alone would keep it.\n await this.prunePackageSubgraphs(\n DOCUMENT_MODEL_SUBGRAPH_SOURCE,\n registeredNames,\n );\n await this.updateRouter();\n this.logger.info(\n \"Regenerated document model subgraphs with @count models\",\n models.length,\n );\n } catch (error) {\n this.logger.error(\n \"Failed to regenerate document model subgraphs: @error\",\n error,\n );\n throw error;\n }\n }\n\n async #setupCoreSubgraphs(\n supergraph: string,\n coreSubgraphs: SubgraphClass[],\n ) {\n for (const subgraph of coreSubgraphs) {\n try {\n await this.registerSubgraph(subgraph, supergraph, true);\n } catch (error) {\n this.logger.error(\n `Failed to setup core subgraph ${subgraph.name}`,\n error,\n );\n }\n }\n\n return this.#setupSubgraphs(this.coreSubgraphsMap);\n }\n\n async #setupDocumentModelSubgraphs(\n supergraph: string,\n documentModels: DocumentModelModule[],\n ): Promise<Set<string>> {\n const latestDocumentModels =\n filterLatestDocumentModelVersions(documentModels);\n const registeredNames = new Set<string>();\n\n for (const documentModel of latestDocumentModels) {\n if (\n DOCUMENT_MODELS_TO_EXCLUDE.includes(\n documentModel.documentModel.global.id,\n )\n ) {\n continue;\n }\n if (!hasOperationSchemas(documentModel)) {\n continue;\n }\n try {\n const subgraphInstance = new DocumentModelSubgraph(documentModel, {\n http: this.scopeForPackage(CORE_PACKAGE_NAME),\n relationalDb: this.relationalDb,\n analyticsStore: this.analyticsStore,\n reactorClient: this.reactorClient,\n graphqlManager: this,\n syncManager: this.syncManager,\n path: this.path,\n documentPermissionService: this.documentPermissionService,\n authorizationService: this.authorizationService,\n syncServingGate: this.syncServingGate,\n });\n\n await this.#addSubgraphInstance(\n subgraphInstance,\n supergraph,\n false,\n DOCUMENT_MODEL_SUBGRAPH_SOURCE,\n );\n registeredNames.add(subgraphInstance.name);\n } catch (error) {\n this.logger.error(\n `Failed to setup document model subgraph for ${documentModel.documentModel.global.id}`,\n error instanceof Error ? error.message : error,\n );\n this.logger.debug(\"@error\", error);\n }\n }\n\n // Document model subgraph instances are added to this.subgraphs above.\n // Their handlers are wired in _updateRouter() → #setupSubgraphs(this.subgraphs),\n // which is called at the end of init() via updateRouter(). We intentionally do\n // NOT call #setupSubgraphs(this.coreSubgraphsMap) here - doing so would\n // create duplicate Apollo servers for the same core-subgraph schemas, which\n // in the new IGatewayAdapter architecture hangs #waitForServer and blocks init().\n\n return registeredNames;\n }\n\n /** Core subgraph names are reserved: they register with core=true during\n * init() and no package subgraph may take one of their names. */\n #isCoreNameReserved(name: string): boolean {\n for (const subgraphs of this.coreSubgraphsMap.values()) {\n if (subgraphs.some((it) => it.name === name)) return true;\n }\n return false;\n }\n\n async #addSubgraphInstance(\n subgraphInstance: ISubgraph,\n supergraph = \"\",\n core = false,\n packageName?: string,\n ) {\n // A package subgraph may not take a name a core subgraph has registered:\n // the in-process handler map is keyed by bare name, so a same-name\n // subgraph would shadow the core one (issue #2972). Reject rather than\n // throw - package registration runs from a detached async closure in\n // server.ts, where a throw is an unhandled rejection that takes the\n // host down.\n if (!core && this.#isCoreNameReserved(subgraphInstance.name)) {\n this.logger.error(\n \"Rejecting subgraph @name: name is reserved by a registered core subgraph\",\n subgraphInstance.name,\n );\n return undefined;\n }\n\n const subgraphsMap = core ? this.coreSubgraphsMap : this.subgraphs;\n\n const existingSubgraph = subgraphsMap\n .get(supergraph)\n ?.find((it) => it.name === subgraphInstance.name);\n\n // Re-registering the same instance is a no-op.\n if (existingSubgraph === subgraphInstance) {\n this.logger.debug(\n `Skipping duplicate subgraph: ${subgraphInstance.name}`,\n );\n return existingSubgraph;\n }\n\n // Same name, different instance: replace (e.g. package hot-reload).\n if (existingSubgraph) {\n await this.#removeSubgraphInstance(existingSubgraph);\n }\n\n await subgraphInstance.onSetup?.();\n\n const subgraphs = subgraphsMap.get(supergraph) ?? [];\n subgraphs.push(subgraphInstance);\n subgraphsMap.set(supergraph, subgraphs);\n\n if (supergraph !== \"\" && supergraph !== \"graphql\") {\n subgraphsMap.get(\"graphql\")?.push(subgraphInstance);\n }\n\n if (packageName !== undefined) {\n let byName = this.packageSubgraphs.get(packageName);\n if (!byName) {\n byName = new Map();\n this.packageSubgraphs.set(packageName, byName);\n }\n byName.set(subgraphInstance.name, subgraphInstance);\n }\n this.logger.info(\n `${existingSubgraph ? \"Replaced\" : \"Registered\"} ${this.path.endsWith(\"/\") ? this.path : this.path + \"/\"}${supergraph ? supergraph + \"/\" : \"\"}${subgraphInstance.name} subgraph.`,\n );\n return subgraphInstance;\n }\n\n /**\n * Tear down a subgraph instance: disconnect it, drop it from every\n * bucket, unmount its route, dispose its WebSocket handler, and remove\n * its internal handler. Used when a subgraph is replaced or its package\n * is removed; #setupSubgraphs then never re-mounts it.\n */\n async #removeSubgraphInstance(instance: ISubgraph) {\n try {\n await instance.onDisconnect?.();\n } catch (error) {\n this.logger.error(\n \"Error disconnecting subgraph @name: @error\",\n instance.name,\n error,\n );\n }\n\n for (const subgraphsMap of [this.coreSubgraphsMap, this.subgraphs]) {\n for (const [bucket, subgraphs] of subgraphsMap.entries()) {\n if (!subgraphs.includes(instance)) {\n continue;\n }\n subgraphsMap.set(\n bucket,\n subgraphs.filter((it) => it !== instance),\n );\n\n const subgraphPath = this.#getSubgraphPath(instance, bucket);\n this.subgraphHandlerCache.delete(subgraphPath);\n\n const routeHandle = this.subgraphRouteHandles.get(subgraphPath);\n if (routeHandle !== undefined) {\n routeHandle.dispose();\n this.subgraphRouteHandles.delete(subgraphPath);\n }\n this.#disposeSSERoute(subgraphPath);\n\n const wsDisposer = this.subgraphWsDisposers.get(subgraphPath);\n if (wsDisposer) {\n this.subgraphWsDisposers.delete(subgraphPath);\n try {\n await wsDisposer.dispose();\n } catch (error) {\n this.logger.error(\n \"Error disposing subgraph websocket @name: @error\",\n instance.name,\n error,\n );\n }\n }\n }\n }\n\n const internalHandler = this.#internalSubgraphHandlers.get(instance.name);\n if (internalHandler?.subgraph === instance) {\n this.#internalSubgraphHandlers.delete(instance.name);\n }\n\n for (const [packageName, byName] of this.packageSubgraphs) {\n if (byName.get(instance.name) !== instance) continue;\n byName.delete(instance.name);\n if (byName.size === 0) {\n this.packageSubgraphs.delete(packageName);\n }\n }\n }\n\n /**\n * Register a pre-constructed subgraph instance.\n * Use this when you need to pass custom dependencies to a subgraph.\n */\n async registerSubgraphInstance(\n subgraphInstance: ISubgraph,\n supergraph = \"\",\n core = false,\n ) {\n return this.#addSubgraphInstance(subgraphInstance, supergraph, core);\n }\n\n /**\n * Get the base path used for subgraph registration.\n */\n getBasePath(): string {\n return this.path;\n }\n\n /**\n * Get the authorization service shared with subgraphs. Use this when\n * constructing a subgraph instance externally for\n * {@link registerSubgraphInstance}.\n */\n getAuthorizationService(): IAuthorizationService {\n return this.authorizationService;\n }\n\n /**\n * The HTTP scope a package's subgraphs get. Falls back to a scope over a\n * throwaway service when route hosting is not configured, so a subgraph can\n * always rely on `args.http` existing.\n */\n scopeForPackage(packageName: string): IHttpScope {\n this.#fallbackRoutes ??=\n this.httpRoutes ??\n new HttpRouteService({\n httpAdapter: this.httpAdapter,\n basePath: this.path,\n authService: this.authService,\n });\n // Non-throwing: a package key with no usable name yields a scope that\n // refuses registrations, rather than taking the host down at boot.\n return this.#fallbackRoutes.scopeForOrNull(packageName);\n }\n\n /**\n * Register a subgraph class. `packageName` labels the resulting instance\n * with its contributing package so the instance can be torn down when the\n * package is removed or drops the subgraph (see unregisterPackage and\n * prunePackageSubgraphs), and decides the namespace its REST routes and\n * webhooks live under.\n */\n async registerSubgraph(\n subgraph: SubgraphClass,\n supergraph = \"\",\n core = false,\n packageName?: string,\n ) {\n const subgraphInstance = new subgraph({\n // Left undefined, the subgraph is core rather than contributed, and its\n // routes hang off reactor-api's own namespace. Not defaulted in the\n // parameter, because `undefined` is what keeps a core subgraph out of\n // `packageSubgraphs` and so out of package teardown.\n http: this.scopeForPackage(packageName ?? CORE_PACKAGE_NAME),\n relationalDb: this.relationalDb,\n analyticsStore: this.analyticsStore,\n reactorClient: this.reactorClient,\n graphqlManager: this,\n syncManager: this.syncManager,\n path: this.path,\n documentPermissionService: this.documentPermissionService,\n authorizationService: this.authorizationService,\n syncServingGate: this.syncServingGate,\n });\n\n return this.#addSubgraphInstance(\n subgraphInstance,\n supergraph,\n core,\n packageName,\n );\n }\n\n /**\n * Tear down every subgraph instance registered from `packageName`:\n * disconnects the instances, unmounts their routes, disposes their\n * WebSocket handlers, then refreshes the router so the supergraph SDL and\n * the supergraph SSE handler no longer reference them. No-op if the\n * package has no registered subgraphs.\n */\n async unregisterPackage(packageName: string): Promise<void> {\n // Routes and webhooks belong to the package, not to its subgraphs, so this\n // runs before the early return below: a package may contribute a processor\n // that registers routes and no subgraph at all, and its routes still have\n // to go. A route that outlives its package answers against unloaded code.\n this.#disposeHttpScope(packageName);\n\n const byName = this.packageSubgraphs.get(packageName);\n if (!byName || byName.size === 0) return;\n for (const instance of Array.from(byName.values())) {\n await this.#removeSubgraphInstance(instance);\n }\n await this.updateRouter();\n }\n\n /**\n * Releases the package's HTTP scope: every route it mounted, and its webhook\n * registrations. Idempotent, and silent for a package that never had one.\n */\n #disposeHttpScope(packageName: string): void {\n const routes = this.#fallbackRoutes ?? this.httpRoutes;\n try {\n routes?.disposeScope(packageName);\n } catch (error) {\n // Teardown must not be the thing that fails: a package whose name never\n // resolved to a namespace has nothing mounted to release anyway.\n this.logger.warn(\n `Failed to release HTTP routes for \"${packageName}\": @error`,\n error,\n );\n }\n }\n\n /**\n * Remove this package's registered subgraphs whose names are not in\n * `keepNames` — the package is still loaded but dropped some of its\n * subgraphs. Refreshes the router if anything was removed.\n */\n async prunePackageSubgraphs(\n packageName: string,\n keepNames: ReadonlySet<string>,\n ): Promise<void> {\n const byName = this.packageSubgraphs.get(packageName);\n if (!byName) return;\n let removed = 0;\n for (const [name, instance] of Array.from(byName.entries())) {\n if (!keepNames.has(name)) {\n await this.#removeSubgraphInstance(instance);\n removed++;\n }\n }\n if (removed > 0) {\n await this.updateRouter();\n }\n }\n\n /** Find a registered subgraph by name, core or package-contributed. */\n getSubgraphByName(name: string): ISubgraph | undefined {\n for (const subgraphs of [\n ...this.coreSubgraphsMap.values(),\n ...this.subgraphs.values(),\n ]) {\n const found = subgraphs.find((subgraph) => subgraph.name === name);\n if (found) {\n return found;\n }\n }\n return undefined;\n }\n\n /** Whether a registered subgraph has a live handler, i.e. whether\n * {@link executeSubgraphQuery} can reach it right now. */\n hasSubgraphHandler(name: string): boolean {\n return this.#internalSubgraphHandlers.has(name);\n }\n\n /** Run a query against one registered subgraph in-process: the subgraph's own\n * handler, without a socket or the auth/drive middleware. Trusted callers. */\n async executeSubgraphQuery<T>(\n subgraphName: string,\n query: string,\n variables: Record<string, unknown>,\n ): Promise<T> {\n const entry = this.#internalSubgraphHandlers.get(subgraphName);\n if (!entry) {\n throw new Error(\n this.getSubgraphByName(subgraphName)\n ? `Subgraph \"${subgraphName}\" is registered but has no handler yet`\n : `Subgraph \"${subgraphName}\" is not registered`,\n );\n }\n\n // Address the subgraph at its real mount path so resolvers and plugins that\n // read the request URL see what an external caller would.\n const url = new URL(entry.path, `http://localhost:${this.port}/`);\n const response = await entry.handler(\n new Request(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n },\n body: JSON.stringify({ query, variables }),\n }),\n );\n if (!response.ok) {\n // Keep the body: Apollo reports validation failures as a 400 whose only\n // description of what went wrong is in there.\n const detail = await response.text().catch(() => \"\");\n throw new Error(\n `Subgraph \"${subgraphName}\" query failed: ${response.status}${\n detail ? ` ${detail}` : \"\"\n }`,\n );\n }\n\n const body = (await response.json()) as {\n data?: T;\n errors?: { message: string }[];\n };\n if (body.errors?.length) {\n throw new Error(body.errors.map((error) => error.message).join(\"; \"));\n }\n if (!body.data) {\n throw new Error(`Subgraph \"${subgraphName}\" returned no data`);\n }\n return body.data;\n }\n\n updateRouter = debounce(this._updateRouter.bind(this), 1000);\n\n private async _updateRouter() {\n this.logger.debug(\"Updating router\");\n\n await this.#setupSubgraphs(this.subgraphs);\n\n try {\n await this.gatewayAdapter.updateSupergraph();\n this.logger.debug(\"Updated Apollo Gateway supergraph\");\n } catch (error) {\n this.logger.error(\n \"Failed to update Apollo Gateway supergraph: @error\",\n error,\n );\n }\n\n // Refresh the supergraph-level SSE handler so it picks up\n // any newly registered subscription-enabled subgraphs.\n const superGraphPath = path.posix.join(this.path, \"graphql\");\n this.#setupSupergraphSSE(superGraphPath);\n }\n\n getAdditionalContextFields = () => {\n return this.contextFields;\n };\n\n setAdditionalContextFields(fields: Record<string, any>) {\n this.contextFields = { ...this.contextFields, ...fields };\n }\n\n #makeContextFactory(): GatewayContextFactory<Context> {\n return (request: Request): Promise<Context> => {\n const authCtx = getAuthContext(request);\n const driveId = getRequestDriveId(request);\n const headers: IncomingHttpHeaders = {};\n request.headers.forEach((v, k) => {\n headers[k] = v;\n });\n return Promise.resolve<Context>({\n headers,\n db: this.relationalDb,\n ...this.getAdditionalContextFields(),\n driveId,\n user: authCtx?.user,\n });\n };\n }\n\n #makeWsContextFactory(): WsHandlers<Context> {\n return createWsAuthHandlers({\n authService: this.authService,\n // Read at call time: init() installs this after the manager is built.\n requireAuthenticatedCaller: () =>\n this.#requireAuthMiddleware !== undefined,\n logger: this.logger,\n buildContext: (connectionParams, user) => {\n const context: Context = {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n headers: connectionParams as any,\n db: this.relationalDb,\n ...this.getAdditionalContextFields(),\n };\n if (user) context.user = user;\n return context;\n },\n });\n }\n\n setSupergraph(supergraph: string, subgraphs: ISubgraph[]) {\n // setSupergraph bypasses #addSubgraphInstance, so apply the same\n // reserved-name guard here: drop incoming subgraphs that would shadow a\n // registered core subgraph, keep the rest.\n const accepted: ISubgraph[] = [];\n for (const subgraph of subgraphs) {\n if (this.#isCoreNameReserved(subgraph.name)) {\n this.logger.error(\n \"Rejecting subgraph @name: name is reserved by a registered core subgraph\",\n subgraph.name,\n );\n continue;\n }\n accepted.push(subgraph);\n }\n this.subgraphs.set(supergraph, accepted);\n const globalSubgraphs = this.subgraphs.get(\"graphql\");\n if (globalSubgraphs) {\n this.subgraphs.set(\"graphql\", [...globalSubgraphs, ...accepted]);\n } else {\n this.subgraphs.set(\"graphql\", accepted);\n }\n return this.updateRouter();\n }\n\n async shutdown(): Promise<void> {\n this.logger.info(\"Shutting down GraphQL Manager\");\n\n // Dispose per-subgraph WebSocket handlers before closing the WS server.\n for (const disposer of this.subgraphWsDisposers.values()) {\n await disposer.dispose();\n }\n this.subgraphWsDisposers.clear();\n\n // Stop all Apollo servers (per-subgraph + federation gateway) via the adapter.\n await this.gatewayAdapter.stop();\n\n return new Promise((resolve) => {\n this.wsServer.close(() => {\n this.logger.info(\"WebSocket server closed\");\n resolve();\n });\n });\n }\n\n // The mount path is owned by the host: the manager's base path, never the\n // subgraph's own `path` field, which a package subgraph can overwrite with a\n // field initializer (it runs after super()).\n #getSubgraphPath(subgraph: ISubgraph, supergraph: string) {\n return path.posix.join(this.path, supergraph, subgraph.name);\n }\n\n /** The in-process handler map is keyed by bare name, so two distinct\n * subgraphs sharing one name would shadow each other: keep the first. */\n #setInternalSubgraphHandler(\n subgraph: ISubgraph,\n subgraphPath: string,\n handler: FetchHandler,\n ) {\n const existing = this.#internalSubgraphHandlers.get(subgraph.name);\n if (existing && existing.subgraph !== subgraph) {\n this.logger.warn(\n \"Two subgraphs are named @name (@kept and @ignored); in-process queries keep the first\",\n subgraph.name,\n existing.path,\n subgraphPath,\n );\n return;\n }\n this.#internalSubgraphHandlers.set(subgraph.name, {\n subgraph,\n path: subgraphPath,\n handler,\n });\n }\n\n async #setupSubgraphs(subgraphsMap: Map<string, ISubgraph[]>) {\n for (const [supergraph, subgraphs] of subgraphsMap.entries()) {\n for (const subgraph of subgraphs) {\n this.logger.debug(`Setting up subgraph ${subgraph.name}`);\n const subgraphPath = this.#getSubgraphPath(subgraph, supergraph);\n try {\n // Skip if handler already cached and mounted — a replaced subgraph\n // invalidates its entries, so a cached path is current. Two\n // different subgraphs landing on the same path: first mounted\n // wins; say so.\n const cached = this.subgraphHandlerCache.get(subgraphPath);\n if (cached) {\n if (cached.subgraph !== subgraph) {\n this.logger.warn(\n \"Subgraph path @path already mounted by @kept; @name is shadowed and will not be mounted\",\n subgraphPath,\n cached.subgraph.name,\n subgraph.name,\n );\n }\n continue;\n }\n\n const schema = createSchema(\n this.cachedDocumentModels,\n subgraph.resolvers,\n subgraph.typeDefs,\n );\n\n const rawHandler = await this.gatewayAdapter.createHandler(\n schema,\n this.#makeContextFactory(),\n );\n const fetchHandler = this.#composeFetchMiddleware(rawHandler);\n this.subgraphHandlerCache.set(subgraphPath, {\n handler: fetchHandler,\n subgraph,\n });\n this.#setInternalSubgraphHandler(subgraph, subgraphPath, rawHandler);\n this.subgraphRouteHandles.set(\n subgraphPath,\n this.httpAdapter.mount(subgraphPath, fetchHandler),\n );\n\n if (subgraph.hasSubscriptions) {\n try {\n const existingDisposer =\n this.subgraphWsDisposers.get(subgraphPath);\n if (existingDisposer) {\n this.logger.warn(\n \"Overwriting existing WebSocket disposer for subgraph at path @path\",\n subgraphPath,\n );\n }\n const wsDisposer = this.gatewayAdapter.attachWebSocket(\n this.wsServer,\n schema,\n this.#makeWsContextFactory(),\n );\n this.subgraphWsDisposers.set(subgraphPath, wsDisposer);\n this.logger.debug(\n `WebSocket subscriptions enabled for ${subgraph.name}`,\n );\n } catch (error) {\n this.logger.error(\n \"Failed to setup websocket for subgraph @name at path @path: @error\",\n subgraph.name,\n subgraphPath,\n error,\n );\n }\n\n // Set up SSE (Server-Sent Events) transport alongside WebSocket.\n // Clients can use SSE by sending POST requests with\n // Accept: text/event-stream to the /stream sub-path.\n try {\n this.#setupSSEHandler(schema, subgraphPath);\n this.logger.debug(\n `SSE subscriptions enabled for ${subgraph.name}`,\n );\n } catch (error) {\n this.logger.error(\n \"Failed to setup SSE for subgraph @name at path @path: @error\",\n subgraph.name,\n subgraphPath,\n error,\n );\n }\n }\n } catch (error) {\n this.logger.error(\n \"Failed to setup subgraph @name at path @path: @error\",\n subgraph.name,\n subgraphPath,\n error,\n );\n }\n }\n }\n }\n\n #getAllSubgraphs() {\n const subgraphsMap = new Map<string, ISubgraph>();\n for (const [supergraph, subgraphs] of [\n ...this.coreSubgraphsMap.entries(),\n ...this.subgraphs.entries(),\n ]) {\n if (supergraph === \"\") {\n continue;\n }\n\n for (const subgraph of subgraphs) {\n const subgraphPath = this.#getSubgraphPath(subgraph, supergraph);\n subgraphsMap.set(subgraphPath, subgraph);\n }\n }\n return subgraphsMap;\n }\n\n #buildSubgraphSchemaModule(subgraph: ISubgraph) {\n return buildSubgraphSchemaModule(\n this.cachedDocumentModels,\n subgraph.resolvers,\n subgraph.typeDefs,\n );\n }\n\n #getSubgraphDefinitions(): SubgraphDefinition[] {\n const subgraphs = this.#getAllSubgraphs();\n\n const herokuOrLocal = process.env.HEROKU_APP_DEFAULT_DOMAIN_NAME\n ? `https://${process.env.HEROKU_APP_DEFAULT_DOMAIN_NAME}`\n : `http://localhost:${this.port}`;\n\n return Array.from(subgraphs.entries()).map(([subgraphPath, subgraph]) => {\n const module = this.#buildSubgraphSchemaModule(subgraph);\n return {\n name: subgraphPath.replace(\"/\", \":\"),\n typeDefs: module.typeDefs,\n // In-process form: the stitching adapter merges these resolvers into\n // the supergraph; federation adapters ignore the field.\n resolvers: module.resolvers,\n url: `${herokuOrLocal}${subgraphPath}`,\n };\n });\n }\n\n async #createSupergraphGateway() {\n const superGraphPath = path.posix.join(this.path, \"graphql\");\n const rawHandler: FetchHandler =\n await this.gatewayAdapter.createSupergraphHandler(\n () => this.#getSubgraphDefinitions(),\n this.httpServer,\n this.#makeContextFactory(),\n );\n const fetchHandler = this.#composeFetchMiddleware(rawHandler);\n this.httpAdapter.mount(superGraphPath, fetchHandler);\n\n // Set up SSE subscriptions at the supergraph level (/graphql/stream).\n // Build a subscription schema from all subgraphs that define subscriptions.\n this.#setupSupergraphSSE(superGraphPath);\n\n if (!this.initialized) {\n this.logger.info(`Registered ${superGraphPath} supergraph `);\n this.initialized = true;\n }\n return;\n }\n\n /**\n * Set up an SSE subscription endpoint at the supergraph level.\n * Merges the schemas of all subscription-enabled subgraphs so that\n * clients can subscribe at /graphql/stream without knowing individual\n * subgraph paths.\n */\n #setupSupergraphSSE(superGraphPath: string) {\n const allSubgraphs = this.#getAllSubgraphs();\n\n const modules = Array.from(allSubgraphs.values())\n .filter((subgraph) => subgraph.hasSubscriptions)\n .map((subgraph) => this.#buildSubgraphSchemaModule(subgraph));\n\n if (modules.length === 0) {\n // No subscription-capable subgraphs left: drop the SSE route rather\n // than keep serving an empty merged schema.\n this.#disposeSSERoute(superGraphPath);\n return;\n }\n\n try {\n const mergedSchema = createMergedSchema(modules);\n this.#setupSSEHandler(mergedSchema, superGraphPath);\n this.logger.debug(\n `SSE subscriptions enabled at supergraph level (merged from ${modules.length} subgraph(s))`,\n );\n } catch (error) {\n this.logger.error(\"Failed to setup supergraph SSE: @error\", error);\n }\n }\n\n /**\n * Set up a GraphQL-over-SSE handler at `<basePath>/stream`.\n *\n * Clients subscribe by sending a POST with `Accept: text/event-stream`\n * to the `/stream` sub-path. Authentication is handled by the normal\n * Express middleware (Authorization header), unlike WebSocket which\n * needs its own connectionParams-based auth.\n */\n #setupSSEHandler(schema: GraphQLSchema, basePath: string) {\n const ssePath = basePath + \"/stream\";\n const rawHandler = createGraphQLSSEHandler({\n schema,\n contextFactory: this.#makeContextFactory(),\n });\n const handler = this.#composeFetchMiddleware(rawHandler);\n // Re-created on every router update: replace this path's previous route\n // rather than pile another on top of it, and leave other paths' alone.\n this.#disposeSSERoute(basePath);\n this.sseRouteHandles.set(\n ssePath,\n this.httpAdapter.mount(ssePath, handler, { exact: true }),\n );\n }\n\n #disposeSSERoute(basePath: string): void {\n const ssePath = basePath + \"/stream\";\n const handle = this.sseRouteHandles.get(ssePath);\n if (handle !== undefined) {\n handle.dispose();\n this.sseRouteHandles.delete(ssePath);\n }\n }\n\n /**\n * Compose the request-level fetch middleware chain. Auth runs first\n * (so we don't validate shard before knowing the request is even\n * authorized); the require-authenticated-caller middleware runs next,\n * before shard validation, so an anonymous caller is rejected with a\n * 401 rather than a 421; drive-ownership validation runs last.\n */\n #composeFetchMiddleware(rawHandler: FetchHandler): FetchHandler {\n let handler = rawHandler;\n if (this.#driveMiddleware) {\n handler = this.#driveMiddleware(handler);\n }\n if (this.#requireAuthMiddleware) {\n handler = this.#requireAuthMiddleware(handler);\n }\n if (this.#authMiddleware) {\n handler = this.#authMiddleware(handler);\n }\n return handler;\n }\n}\n","import { GraphQLError } from \"graphql\";\nimport type { IAuthorizationService } from \"../../services/authorization.service.js\";\nimport type { PackageManagementService } from \"../../services/package-management.service.js\";\nimport type { InstalledPackageInfo } from \"../../services/package-storage.js\";\nimport type { Context } from \"../types.js\";\n\nfunction requireAdmin(\n authorizationService: IAuthorizationService,\n ctx: Context,\n): void {\n if (!authorizationService.isSupremeAdmin(ctx.user?.address)) {\n throw new GraphQLError(\"Admin access required\");\n }\n}\n\nfunction formatPackageInfo(info: InstalledPackageInfo) {\n return {\n name: info.name,\n version: info.version ?? null,\n registryUrl: info.registryUrl,\n installedAt: info.installedAt.toISOString(),\n documentTypes: info.documentTypes,\n };\n}\n\nexport async function installedPackages(\n service: PackageManagementService,\n): Promise<ReturnType<typeof formatPackageInfo>[]> {\n const packages = await service.getInstalledPackages();\n return packages.map(formatPackageInfo);\n}\n\nexport async function installedPackage(\n service: PackageManagementService,\n args: { name: string },\n): Promise<ReturnType<typeof formatPackageInfo> | null> {\n const pkg = await service.getInstalledPackage(args.name);\n return pkg ? formatPackageInfo(pkg) : null;\n}\n\nexport async function installPackage(\n service: PackageManagementService,\n authorizationService: IAuthorizationService,\n args: { name: string; registryUrl?: string | null },\n ctx: Context,\n): Promise<{\n package: ReturnType<typeof formatPackageInfo>;\n documentModelsLoaded: number;\n}> {\n requireAdmin(authorizationService, ctx);\n\n const result = await service.installPackage(\n args.name,\n args.registryUrl ?? undefined,\n );\n\n return {\n package: formatPackageInfo(result.package),\n documentModelsLoaded: result.documentModelsLoaded,\n };\n}\n\nexport async function uninstallPackage(\n service: PackageManagementService,\n authorizationService: IAuthorizationService,\n args: { name: string },\n ctx: Context,\n): Promise<boolean> {\n requireAdmin(authorizationService, ctx);\n\n return service.uninstallPackage(args.name);\n}\n","\"# Packages Subgraph Schema\\n# Provides operations for runtime package management\\n\\nscalar DateTime\\n\\n# Information about an installed package\\ntype InstalledPackage {\\n # Package name (e.g., \\\"@powerhousedao/vetra\\\")\\n name: String!\\n # Package version if known\\n version: String\\n # Registry URL where the package was installed from\\n registryUrl: String!\\n # Timestamp when the package was installed\\n installedAt: DateTime!\\n # Document type IDs provided by this package\\n documentTypes: [String!]!\\n}\\n\\n# Result returned after installing a package\\ntype InstallPackageResult {\\n # The installed package information\\n package: InstalledPackage!\\n # Number of document models loaded from the package\\n documentModelsLoaded: Int!\\n}\\n\\ntype PackagesQueries {\\n # Get all installed packages\\n installedPackages: [InstalledPackage!]!\\n\\n # Get information about a specific installed package\\n installedPackage(name: String!): InstalledPackage\\n}\\n\\ntype PackagesMutations {\\n # Install a package from the registry (requires admin access)\\n installPackage(\\n # Package name (e.g., \\\"@powerhousedao/vetra\\\")\\n name: String!\\n # Registry URL (uses default if not provided)\\n registryUrl: String\\n ): InstallPackageResult!\\n\\n # Uninstall a package (requires admin access)\\n uninstallPackage(\\n # Package name to uninstall\\n name: String!\\n ): Boolean!\\n}\\n\\ntype Query {\\n Packages: PackagesQueries!\\n}\\n\\ntype Mutation {\\n Packages: PackagesMutations!\\n}\\n\"","import { ConsoleLogger } from \"document-model\";\nimport { gql } from \"graphql-tag\";\nimport type { PackageManagementService } from \"../../services/package-management.service.js\";\nimport { BaseSubgraph } from \"../base-subgraph.js\";\nimport type { Context, SubgraphArgs } from \"../types.js\";\nimport * as resolvers from \"./resolvers.js\";\nimport schemaSource from \"./schema.graphql\";\n\nexport interface PackagesSubgraphArgs extends SubgraphArgs {\n packageManagementService: PackageManagementService;\n}\n\nexport class PackagesSubgraph extends BaseSubgraph {\n private logger = new ConsoleLogger([\"PackagesSubgraph\"]);\n private packageManagementService: PackageManagementService;\n\n constructor(args: PackagesSubgraphArgs) {\n super(args);\n this.packageManagementService = args.packageManagementService;\n this.logger.verbose(`constructor()`);\n }\n\n name = \"packages\";\n hasSubscriptions = false;\n\n typeDefs = gql(schemaSource);\n\n resolvers = {\n Query: {\n Packages: () => ({}),\n },\n PackagesQueries: {\n installedPackages: async () => {\n this.logger.debug(\"installedPackages\");\n try {\n return await resolvers.installedPackages(\n this.packageManagementService,\n );\n } catch (error) {\n this.logger.error(\"Error in installedPackages: @error\", error);\n throw error;\n }\n },\n\n installedPackage: async (_parent: unknown, args: { name: string }) => {\n this.logger.debug(\"installedPackage(@args)\", args);\n try {\n return await resolvers.installedPackage(\n this.packageManagementService,\n args,\n );\n } catch (error) {\n this.logger.error(\"Error in installedPackage: @error\", error);\n throw error;\n }\n },\n },\n\n Mutation: {\n Packages: () => ({}),\n },\n\n PackagesMutations: {\n installPackage: async (\n _parent: unknown,\n args: { name: string; registryUrl?: string | null },\n ctx: Context,\n ) => {\n this.logger.debug(\"installPackage(@args)\", args);\n try {\n return await resolvers.installPackage(\n this.packageManagementService,\n this.authorizationService,\n args,\n ctx,\n );\n } catch (error) {\n this.logger.error(\"Error in installPackage: @error\", error);\n throw error;\n }\n },\n\n uninstallPackage: async (\n _parent: unknown,\n args: { name: string },\n ctx: Context,\n ) => {\n this.logger.debug(\"uninstallPackage(@args)\", args);\n try {\n return await resolvers.uninstallPackage(\n this.packageManagementService,\n this.authorizationService,\n args,\n ctx,\n );\n } catch (error) {\n this.logger.error(\"Error in uninstallPackage: @error\", error);\n throw error;\n }\n },\n },\n };\n\n onSetup(): Promise<void> {\n this.logger.debug(\"Setting up PackagesSubgraph\");\n return Promise.resolve();\n }\n}\n","import lzString from \"lz-string\";\n\n/**\n * The lz-compressed `explorerURLState` parameter carried by switchboard\n * explorer URLs: the JSON payload produced by\n * `buildDocumentSubgraphQuery` in `@powerhousedao/reactor-browser`,\n * `{ document, variables, headers? }` with `variables` and `headers`\n * already JSON-stringified.\n */\nexport interface ExplorerUrlState {\n /** The GraphQL query to prefill in GraphiQL. */\n query: string;\n /** JSON-stringified variables, as stored in the payload. */\n variables?: string;\n /** Request headers for the GraphiQL fetcher (e.g. Authorization). */\n headers?: Record<string, string>;\n}\n\n/**\n * Decodes an `explorerURLState` URL parameter. Returns `null` for anything\n * that is not a valid lz-compressed payload with a non-empty `document`.\n */\nexport function decodeExplorerUrlState(\n encoded: string,\n): ExplorerUrlState | null {\n try {\n const decompressed = lzString.decompressFromEncodedURIComponent(encoded);\n if (!decompressed) {\n return null;\n }\n const payload = JSON.parse(decompressed) as Record<string, unknown>;\n if (typeof payload.document !== \"string\" || payload.document.length === 0) {\n return null;\n }\n const variables =\n typeof payload.variables === \"string\" ? payload.variables : undefined;\n let headers: Record<string, string> | undefined;\n if (typeof payload.headers === \"string\") {\n const parsed: unknown = JSON.parse(payload.headers);\n if (parsed && typeof parsed === \"object\") {\n headers = parsed as Record<string, string>;\n }\n }\n return { query: payload.document, variables, headers };\n } catch {\n return null;\n }\n}\n\n/**\n * Pinned CDN versions for GraphiQL playground dependencies.\n * Using pinned versions avoids unpkg.com redirect issues that can\n * trigger CORS errors in the browser.\n */\nconst CDN_VERSIONS = {\n react: \"18.3.1\",\n reactDom: \"18.3.1\",\n graphiql: \"3.8.3\",\n pluginExplorer: \"4.0.0\",\n};\n\n/**\n * Escape a string for embedding as a single-quoted JS string literal inside\n * an HTML `<script>` block. The payload reaches the browser through an\n * attacker-controllable URL parameter, so the embedding must survive two\n * parsers: HTML (a `</script>` inside the string would end the script\n * element and start a new, attacker-authored one) and JS (backticks,\n * `${...}` and quotes in the content would otherwise break out of the\n * literal). Backslash, quote, CR and LF escapes keep the literal valid;\n * every `<` becomes `\\u003c`, which no HTML parser reads as a tag opener.\n * The escapes resolve when the script parses, so the in-memory value is\n * byte-identical to the input.\n */\nfunction jsStringEscape(value: string): string {\n return value\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/'/g, \"\\\\'\")\n .replace(/\\r/g, \"\\\\r\")\n .replace(/\\n/g, \"\\\\n\")\n .replace(/</g, \"\\\\u003c\");\n}\n\n/**\n * JSON is already a valid JS object/string literal; the only HTML-hostile\n * byte left is `<` (e.g. `</script>` inside a string value).\n */\nfunction jsJsonEscape(json: string): string {\n return json.replace(/</g, \"\\\\u003c\");\n}\n\nexport function renderGraphqlPlayground(\n url: string,\n query?: string,\n headers: Record<string, string> = {},\n variables?: string,\n): string {\n return `<!doctype html>\n <html lang=\"en\">\n <head>\n <title>GraphiQL</title>\n <style>\n body {\n height: 100%;\n margin: 0;\n width: 100%;\n overflow: hidden;\n }\n\n #graphiql {\n height: 100vh;\n }\n </style>\n <script\n src=\"https://unpkg.com/react@${CDN_VERSIONS.react}/umd/react.production.min.js\"\n ></script>\n <script\n src=\"https://unpkg.com/react-dom@${CDN_VERSIONS.reactDom}/umd/react-dom.production.min.js\"\n ></script>\n <script\n src=\"https://unpkg.com/graphiql@${CDN_VERSIONS.graphiql}/graphiql.min.js\"\n ></script>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/graphiql@${CDN_VERSIONS.graphiql}/graphiql.min.css\" />\n <script\n src=\"https://unpkg.com/@graphiql/plugin-explorer@${CDN_VERSIONS.pluginExplorer}/dist/index.umd.js\"\n ></script>\n <link\n rel=\"stylesheet\"\n href=\"https://unpkg.com/@graphiql/plugin-explorer@${CDN_VERSIONS.pluginExplorer}/dist/style.css\"\n />\n </head>\n\n <body>\n <div id=\"graphiql\">Loading...</div>\n <script>\n var fetcher = GraphiQL.createFetcher({\n url: '${jsStringEscape(url)}',\n headers: ${jsJsonEscape(JSON.stringify(headers))}\n });\n var defaultQuery = ${\n query ? `'${jsStringEscape(query)}'` : \"undefined\"\n };\n var defaultVariables = ${\n variables ? `'${jsStringEscape(variables)}'` : \"undefined\"\n };\n\n // GraphiQL only applies defaultQuery/variables when the editor has\n // no persisted value. Overwrite any stale persisted state so a\n // returning user still gets the document-scoped query/variables\n // instead of their last session's.\n if (defaultQuery && localStorage.getItem(\"graphiql:query\")) {\n localStorage.setItem(\"graphiql:query\", defaultQuery);\n }\n if (defaultVariables && localStorage.getItem(\"graphiql:variables\")) {\n localStorage.setItem(\"graphiql:variables\", defaultVariables);\n }\n\n var explorerPlugin = GraphiQLPluginExplorer.explorerPlugin();\n\n function GraphiQLWithExplorer() {\n return React.createElement(GraphiQL, {\n fetcher: fetcher,\n defaultEditorToolsVisibility: true,\n plugins: [explorerPlugin],\n defaultQuery: defaultQuery,\n variables: defaultVariables\n });\n }\n\n const root = ReactDOM.createRoot(document.getElementById('graphiql'));\n root.render(React.createElement(GraphiQLWithExplorer));\n </script>\n </body>\n </html>`;\n}\n","import type { DocumentNode } from \"graphql\";\nimport { print } from \"graphql\";\nimport type { Requester } from \"./gen/graphql.js\";\n\nexport type FetchLike = (\n input: URL | string,\n init: RequestInit,\n) => Promise<Response>;\n\ninterface GraphQLResponse<T = unknown> {\n data?: T;\n errors?: Array<{ message: string; locations?: unknown; path?: unknown }>;\n}\n\nexport function createFetchRequester(\n url: string,\n fetchImpl: FetchLike,\n baseHeaders: Record<string, string> = {},\n): Requester {\n return async <R, V>(document: DocumentNode, variables?: V) => {\n const res = await fetchImpl(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n ...baseHeaders,\n },\n body: JSON.stringify({ query: print(document), variables }),\n });\n\n if (!res.ok) {\n throw new Error(`GraphQL HTTP ${res.status}`);\n }\n\n const json = (await res.json()) as GraphQLResponse<R>;\n if (json.errors) {\n throw new Error(JSON.stringify(json.errors));\n }\n\n return json.data as R;\n };\n}\n","import { z } from \"zod\";\n\n// Scalar DTOs\nexport const JSONObjectDTO = z.unknown();\nexport const DateTimeDTO = z.union([z.string(), z.date()]);\n\nexport const DocumentModelStateDTO = z\n .object({\n id: z.string(),\n name: z.string(),\n namespace: z.string().nullable().optional(),\n version: z.string().nullable().optional(),\n specification: JSONObjectDTO.nullable().optional(),\n })\n .strip();\n\nexport const DocumentModelResultPageDTO = z\n .object({\n items: z.array(DocumentModelStateDTO),\n hasNextPage: z.boolean(),\n hasPreviousPage: z.boolean(),\n cursor: z.string().nullable().optional(),\n })\n .strip();\n\nexport const RevisionEntryDTO = z\n .object({\n scope: z.string(),\n revision: z.number().int(),\n })\n .strip();\n\nexport const PHDocumentDTO = z\n .object({\n id: z.string(),\n slug: z.string().nullable().optional(),\n name: z.string(),\n documentType: z.string(),\n state: JSONObjectDTO,\n revisionsList: z.array(RevisionEntryDTO),\n createdAtUtcIso: DateTimeDTO,\n lastModifiedAtUtcIso: DateTimeDTO,\n })\n .strip();\n\nexport const PHDocumentResultPageDTO = z\n .object({\n items: z.array(PHDocumentDTO),\n hasNextPage: z.boolean(),\n hasPreviousPage: z.boolean(),\n cursor: z.string().nullable().optional(),\n })\n .strip();\n\nexport const DocumentRelationshipDTO = z\n .object({\n sourceId: z.string(),\n targetId: z.string(),\n relationshipType: z.string(),\n metadata: JSONObjectDTO.nullable().optional(),\n createdAt: DateTimeDTO,\n updatedAt: DateTimeDTO,\n })\n .strip();\n\nexport const DocumentRelationshipResultPageDTO = z\n .object({\n items: z.array(DocumentRelationshipDTO),\n hasNextPage: z.boolean(),\n hasPreviousPage: z.boolean(),\n cursor: z.string().nullable().optional(),\n })\n .strip();\n\nexport const DocumentWithChildrenDTO = z\n .object({\n document: PHDocumentDTO,\n childIds: z.array(z.string()),\n })\n .strip();\n\nexport const MoveRelationshipResultDTO = z\n .object({\n source: PHDocumentDTO,\n target: PHDocumentDTO,\n })\n .strip();\n\nexport const JobInfoDTO = z\n .object({\n id: z.string(),\n status: z.string(),\n result: JSONObjectDTO.nullable().optional(),\n error: z.string().nullable().optional(),\n createdAt: DateTimeDTO,\n completedAt: DateTimeDTO.nullable().optional(),\n })\n .strip();\n\n// Operation DTOs for GetDocumentOperations\nexport const ActionSignerUserDTO = z\n .object({\n address: z.string(),\n networkId: z.string(),\n chainId: z.number().int(),\n })\n .strip();\n\nexport const ActionSignerAppDTO = z\n .object({\n name: z.string(),\n key: z.string(),\n })\n .strip();\n\nexport const ActionSignerDTO = z\n .object({\n signatures: z.array(z.string()),\n user: ActionSignerUserDTO.nullable().optional(),\n app: ActionSignerAppDTO.nullable().optional(),\n })\n .strip();\n\nexport const ActionContextDTO = z\n .object({\n signer: ActionSignerDTO.nullable().optional(),\n })\n .strip();\n\nexport const OperationActionDTO = z\n .object({\n id: z.string(),\n type: z.string(),\n timestampUtcMs: z.string(),\n input: z.unknown(),\n scope: z.string(),\n context: ActionContextDTO.nullable().optional(),\n })\n .strip();\n\nexport const OperationDTO = z\n .object({\n index: z.number().int(),\n timestampUtcMs: z.string(),\n hash: z.string(),\n skip: z.number().int(),\n error: z.string().nullable().optional(),\n id: z.string().nullable().optional(),\n action: OperationActionDTO,\n })\n .strip();\n\nexport const OperationResultPageDTO = z\n .object({\n items: z.array(OperationDTO),\n hasNextPage: z.boolean(),\n hasPreviousPage: z.boolean(),\n cursor: z.string().nullable().optional(),\n })\n .strip();\n\nexport const DocumentWithChildrenAndOperationsDTO = z\n .object({\n document: PHDocumentDTO.extend({\n operations: OperationResultPageDTO.optional(),\n }),\n childIds: z.array(z.string()),\n })\n .strip();\n\nexport const DocumentChangeContextDTO = z\n .object({\n parentId: z.string().nullable().optional(),\n childId: z.string().nullable().optional(),\n })\n .strip();\n\nexport const DocumentChangeEventDTO = z\n .object({\n type: z.string(),\n documents: z.array(PHDocumentDTO),\n context: DocumentChangeContextDTO.nullable().optional(),\n })\n .strip();\n\nexport const ActionEvaluationDTO = z\n .object({\n decision: z.enum([\"ALLOW\", \"DENY\"]),\n reason: z.string().nullable().optional(),\n })\n .strip();\n\nexport const ActionEvaluationsDTO = z\n .object({\n evaluations: z.array(ActionEvaluationDTO),\n allAllowed: z.boolean(),\n anyAllowed: z.boolean(),\n allDenied: z.boolean(),\n anyDenied: z.boolean(),\n })\n .strip();\n\nexport const JobChangeEventDTO = z\n .object({\n jobId: z.string(),\n status: z.string(),\n result: JSONObjectDTO.nullable().optional(),\n error: z.string().nullable().optional(),\n })\n .strip();\n","import type { DocumentNode, OperationDefinitionNode } from \"graphql\";\nimport { Kind } from \"graphql\";\nimport type {\n DocumentModelResultPage,\n JobInfo,\n PhDocumentResultPage,\n Requester,\n Sdk,\n} from \"./gen/graphql.js\";\nimport type { FetchLike } from \"./requester.js\";\nimport { createFetchRequester } from \"./requester.js\";\nimport {\n ActionEvaluationsDTO,\n DocumentChangeEventDTO,\n DocumentModelResultPageDTO,\n DocumentRelationshipResultPageDTO,\n DocumentWithChildrenAndOperationsDTO,\n DocumentWithChildrenDTO,\n JobChangeEventDTO,\n JobInfoDTO,\n MoveRelationshipResultDTO,\n OperationResultPageDTO,\n PHDocumentDTO,\n PHDocumentResultPageDTO,\n} from \"./validation.js\";\n\ntype OperationName = keyof Sdk;\ntype OperationHandler = (data: Record<string, unknown>) => void;\n\n// This type enforces that ALL operations from Sdk must have a handler\n// TypeScript will error if any operation is missing\ntype OperationValidators = { [K in OperationName]: OperationHandler };\n\n// Validation handlers for each operation\n// TypeScript will error if any operation from Sdk is missing\nconst operationValidators: OperationValidators = {\n GetDocument: (data) => {\n if (data.document) {\n DocumentWithChildrenDTO.parse(data.document);\n }\n },\n GetDocumentWithOperations: (data) => {\n if (data.document) {\n DocumentWithChildrenAndOperationsDTO.parse(data.document);\n }\n },\n GetDocumentModels: (data) => {\n if (data.documentModels) {\n DocumentModelResultPageDTO.parse(\n data.documentModels as DocumentModelResultPage,\n );\n }\n },\n GetDocumentOutgoingRelationships: (data) => {\n if (data.documentOutgoingRelationships) {\n PHDocumentResultPageDTO.parse(\n data.documentOutgoingRelationships as PhDocumentResultPage,\n );\n }\n },\n GetDocumentIncomingRelationships: (data) => {\n if (data.documentIncomingRelationships) {\n PHDocumentResultPageDTO.parse(\n data.documentIncomingRelationships as PhDocumentResultPage,\n );\n }\n },\n GetDocumentOutgoingRelationshipEdges: (data) => {\n if (data.documentOutgoingRelationshipEdges) {\n DocumentRelationshipResultPageDTO.parse(\n data.documentOutgoingRelationshipEdges,\n );\n }\n },\n GetDocumentIncomingRelationshipEdges: (data) => {\n if (data.documentIncomingRelationshipEdges) {\n DocumentRelationshipResultPageDTO.parse(\n data.documentIncomingRelationshipEdges,\n );\n }\n },\n FindDocuments: (data) => {\n if (data.findDocuments) {\n PHDocumentResultPageDTO.parse(data.findDocuments as PhDocumentResultPage);\n }\n },\n GetDocumentOperations: (data) => {\n if (data.documentOperations) {\n OperationResultPageDTO.parse(data.documentOperations);\n }\n },\n GetJobStatus: (data) => {\n if (data.jobStatus) {\n JobInfoDTO.parse(data.jobStatus as JobInfo);\n }\n },\n EvaluateActions: (data) => {\n if (data.evaluateActions) {\n ActionEvaluationsDTO.parse(data.evaluateActions);\n }\n },\n // Mutations\n CreateDocument: (data) => {\n if (data.createDocument) {\n PHDocumentDTO.parse(data.createDocument);\n }\n },\n CreateEmptyDocument: (data) => {\n if (data.createEmptyDocument) {\n PHDocumentDTO.parse(data.createEmptyDocument);\n }\n },\n MutateDocument: (data) => {\n if (data.mutateDocument) {\n PHDocumentDTO.parse(data.mutateDocument);\n }\n },\n MutateDocumentAsync: (data) => {\n if (data.mutateDocumentAsync) {\n // Returns a job ID string\n }\n },\n RenameDocument: (data) => {\n if (data.renameDocument) {\n PHDocumentDTO.parse(data.renameDocument);\n }\n },\n SetPreferredEditor: (data) => {\n if (data.setPreferredEditor) {\n PHDocumentDTO.parse(data.setPreferredEditor);\n }\n },\n AddRelationship: (data) => {\n if (data.addRelationship) {\n PHDocumentDTO.parse(data.addRelationship);\n }\n },\n UpdateRelationship: (data) => {\n if (data.updateRelationship) {\n PHDocumentDTO.parse(data.updateRelationship);\n }\n },\n RemoveRelationship: (data) => {\n if (data.removeRelationship) {\n PHDocumentDTO.parse(data.removeRelationship);\n }\n },\n MoveRelationship: (data) => {\n if (data.moveRelationship) {\n MoveRelationshipResultDTO.parse(data.moveRelationship);\n }\n },\n DeleteDocument: (data) => {\n if (data.deleteDocument !== undefined) {\n // Returns a boolean\n }\n },\n DeleteDocuments: (data) => {\n if (data.deleteDocuments !== undefined) {\n // Returns a boolean\n }\n },\n // Subscriptions\n DocumentChanges: (data) => {\n if (data.documentChanges) {\n DocumentChangeEventDTO.parse(data.documentChanges);\n }\n },\n JobChanges: (data) => {\n if (data.jobChanges) {\n JobChangeEventDTO.parse(data.jobChanges);\n }\n },\n // Sync operations (used inline by reactor/gql-req-channel.ts, not through this SDK)\n PollSyncEnvelopes: () => {},\n TouchChannel: () => {},\n PushSyncEnvelopes: () => {},\n};\n\nexport function createValidatingRequester(\n url: string,\n fetchImpl: FetchLike,\n headers?: Record<string, string>,\n): Requester {\n const base = createFetchRequester(url, fetchImpl, headers);\n return async <R, V>(\n document: DocumentNode,\n variables?: V,\n options?: RequestInit,\n ): Promise<R> => {\n const data = (await base(document, variables, options)) as R;\n\n // Extract operation name from the document\n const operationDef = document.definitions.find(\n (d): d is OperationDefinitionNode =>\n d.kind === Kind.OPERATION_DEFINITION && !!d.name,\n );\n const operationName = operationDef?.name?.value;\n\n // Validate based on operation name\n if (data && operationName && operationName in operationValidators) {\n const validator = operationValidators[operationName as OperationName];\n validator(data as Record<string, unknown>);\n }\n\n return data;\n };\n}\n","import { getSdk } from \"./gen/graphql.js\";\nimport type { FetchLike } from \"./requester.js\";\nimport { createValidatingRequester } from \"./requester.with-zod.js\";\n\nexport function createReactorGraphQLClient(\n url: string,\n fetchImpl: FetchLike = fetch,\n headers?: Record<string, string>,\n) {\n const requester = createValidatingRequester(url, fetchImpl, headers);\n return getSdk(requester);\n}\n","\"# 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}\\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 TouchChannelInput {\\n id: String!\\n name: String!\\n collectionId: String!\\n filter: RemoteFilterInput!\\n sinceTimestampUtcMs: String!\\n}\\n\\ntype TouchChannelResult {\\n success: Boolean!\\n ackOrdinal: Int!\\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 ): PollSyncEnvelopesResult!\\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(envelopes: [SyncEnvelopeInput!]!): 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\"","import type {\n DocumentChangeEvent,\n IReactorClient,\n JobResultSummary,\n SearchFilter,\n ViewFilter,\n} from \"@powerhousedao/reactor\";\nimport type { AuthSubject } from \"@powerhousedao/shared/document-model\";\nimport { PubSub } from \"graphql-subscriptions\";\n\nconst pubSub = new PubSub();\n\nexport function getPubSub(): PubSub {\n return pubSub;\n}\n\nexport type SubscriptionTriggers = {\n DOCUMENT_CHANGES: string;\n JOB_CHANGES: string;\n};\n\nexport const SUBSCRIPTION_TRIGGERS: SubscriptionTriggers = {\n DOCUMENT_CHANGES: \"DOCUMENT_CHANGES\",\n JOB_CHANGES: \"JOB_CHANGES\",\n};\n\nexport interface DocumentChangesPayload {\n documentChanges: DocumentChangeEvent;\n search: SearchFilter;\n view?: ViewFilter;\n}\n\nexport interface JobChangesPayload {\n jobChanges: {\n jobId: string;\n status: string;\n createdAt: string;\n completedAt: string | null;\n error: string | null;\n result: JobResultSummary | null;\n };\n jobId: string;\n /** Document id used to authorize the subscription; not in the GraphQL event. */\n documentId: string;\n}\n\ntype Feed = { unsubscribe: () => void; subscribers: number };\n\n// Anonymous callers share one feed; `|` cannot occur in an address or a did:key.\nfunction subjectKey(subject: AuthSubject): string {\n return `${subject.address ?? \"\"}|${subject.key ?? \"\"}`;\n}\n\n/**\n * The reactor's change feed, read once per distinct subject and shared by that\n * subject's GraphQL subscriptions. Each feed is read as its subject, so the\n * client withholds what that subject may not read; one feed read with no view\n * would gate every subscriber as the host.\n */\nexport class DocumentChangeFeed {\n readonly #pubSub = new PubSub();\n readonly #feeds = new Map<string, Feed>();\n\n constructor(private readonly reactorClient: IReactorClient) {}\n\n subscribe(\n subject: AuthSubject,\n ): AsyncIterableIterator<DocumentChangesPayload> {\n const key = subjectKey(subject);\n const topic = `${SUBSCRIPTION_TRIGGERS.DOCUMENT_CHANGES}:${key}`;\n const iterator =\n this.#pubSub.asyncIterableIterator<DocumentChangesPayload>(topic);\n this.#acquire(key, topic, subject);\n\n let released = false;\n const release = () => {\n if (!released) {\n released = true;\n this.#release(key);\n }\n };\n\n return {\n next: () => iterator.next(),\n return: () => {\n release();\n return iterator.return();\n },\n throw: (error: unknown) => {\n release();\n return iterator.throw(error);\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n }\n\n #acquire(key: string, topic: string, subject: AuthSubject): void {\n const feed = this.#feeds.get(key);\n if (feed) {\n feed.subscribers++;\n return;\n }\n\n const view: ViewFilter = { subject };\n const unsubscribe = this.reactorClient.subscribe(\n {},\n (event: DocumentChangeEvent) => {\n const payload: DocumentChangesPayload = {\n documentChanges: event,\n search: {},\n view,\n };\n void this.#pubSub.publish(topic, payload);\n },\n view,\n );\n this.#feeds.set(key, { unsubscribe, subscribers: 1 });\n }\n\n #release(key: string): void {\n const feed = this.#feeds.get(key);\n if (!feed) {\n return;\n }\n feed.subscribers--;\n if (feed.subscribers === 0) {\n this.#feeds.delete(key);\n feed.unsubscribe();\n }\n }\n}\n\nconst activeJobSubscriptions = new Map<\n string,\n {\n cancel: () => void;\n refCount: number;\n }\n>();\n\nexport function ensureJobSubscription(\n reactorClient: IReactorClient,\n jobId: string,\n): () => void {\n let subscription = activeJobSubscriptions.get(jobId);\n\n if (!subscription) {\n let isCancelled = false;\n let timeoutId: NodeJS.Timeout | undefined;\n\n const poll = async () => {\n if (isCancelled) {\n return;\n }\n\n const jobInfo = await reactorClient.getJobStatus(jobId);\n const payload: JobChangesPayload = {\n jobChanges: {\n jobId: jobInfo.id,\n status: jobInfo.status,\n createdAt: jobInfo.createdAtUtcIso,\n completedAt: jobInfo.completedAtUtcIso ?? null,\n error: jobInfo.error?.message ?? null,\n result: jobInfo.result ?? null,\n },\n jobId,\n documentId: jobInfo.documentId,\n };\n\n void pubSub.publish(SUBSCRIPTION_TRIGGERS.JOB_CHANGES, payload);\n\n const isTerminal =\n String(jobInfo.status) === \"FAILED\" ||\n String(jobInfo.status) === \"READ_MODELS_READY\" ||\n jobInfo.completedAtUtcIso !== undefined;\n\n if (!isTerminal && !isCancelled) {\n timeoutId = setTimeout(() => {\n void poll().catch((error) => {\n console.error(\"Error polling job status:\", error);\n });\n }, 1000);\n } else if (isTerminal) {\n activeJobSubscriptions.delete(jobId);\n }\n };\n\n void poll().catch((error) => {\n console.error(\"Error starting job polling:\", error);\n });\n\n const cancel = () => {\n isCancelled = true;\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n };\n\n subscription = { cancel, refCount: 0 };\n activeJobSubscriptions.set(jobId, subscription);\n }\n\n subscription.refCount++;\n\n return () => {\n if (subscription) {\n subscription.refCount--;\n if (subscription.refCount === 0) {\n subscription.cancel();\n activeJobSubscriptions.delete(jobId);\n }\n }\n };\n}\n","import { ConsoleLogger } from \"document-model\";\nimport { DriveCollectionId } from \"@powerhousedao/reactor\";\nimport { GraphQLError } from \"graphql\";\nimport { ForbiddenError } from \"../errors.js\";\nimport { withFilter } from \"graphql-subscriptions\";\nimport { gql } from \"graphql-tag\";\nimport schemaSource from \"./schema.graphql\";\nimport {\n AuthorizedDocumentHandle,\n type CanonicalDocumentId,\n} from \"../../services/authorization.service.js\";\nimport { BaseSubgraph } from \"../base-subgraph.js\";\nimport type { Context, SubgraphArgs } from \"../types.js\";\nimport {\n collectChangedDocumentIds,\n matchesJobFilter,\n matchesSearchFilter,\n toGqlDocumentChangeEvent,\n} from \"./adapters.js\";\nimport { isDriveContainerType } from \"./constants.js\";\nimport type { Resolvers } from \"./gen/graphql.js\";\nimport {\n DocumentChangeFeed,\n ensureJobSubscription,\n getPubSub,\n SUBSCRIPTION_TRIGGERS,\n type DocumentChangesPayload,\n type JobChangesPayload,\n} from \"./pubsub.js\";\nimport * as resolvers from \"./resolvers.js\";\n\nexport class ReactorSubgraph extends BaseSubgraph {\n // temp\n private logger = new ConsoleLogger([\"ReactorSubgraph\"]);\n\n constructor(args: SubgraphArgs) {\n super(args);\n this.logger.verbose(`constructor()`);\n }\n\n name = \"r\";\n hasSubscriptions = true;\n\n #documentChanges: DocumentChangeFeed | undefined;\n\n private get documentChanges(): DocumentChangeFeed {\n this.#documentChanges ??= new DocumentChangeFeed(this.reactorClient);\n return this.#documentChanges;\n }\n\n /**\n * Check operation-level permissions for an array of actions.\n * Delegates to base assertCanExecuteOperation for each action.\n */\n private async assertCanExecuteOperations(\n documentId: string,\n actions: readonly unknown[],\n ctx: Context,\n ): Promise<AuthorizedDocumentHandle> {\n let handle = AuthorizedDocumentHandle.skipped(documentId);\n for (const action of actions) {\n if (!action || typeof action !== \"object\") continue;\n const actionObj = action as Record<string, unknown>;\n const operationType = actionObj.type;\n if (typeof operationType !== \"string\") continue;\n\n handle = await this.assertCanExecuteOperation(\n documentId,\n operationType,\n ctx,\n );\n }\n return handle;\n }\n\n /**\n * Returns the drive id when the given identifier (id or slug) refers\n * to a drive document, otherwise undefined. Used by deleteDocument to\n * decide whether to invalidate the drive-ownership cache after a\n * successful delete.\n */\n async #resolveDriveId(identifier: string): Promise<string | undefined> {\n try {\n const doc = await this.reactorClient.get(identifier);\n if (isDriveContainerType(doc.header.documentType)) {\n return doc.header.id;\n }\n return undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Drops the relationship edges whose far-end document the caller cannot read.\n *\n * An edge names two documents, so returning it discloses the far end's id. The\n * document-shaped relationship queries already withhold far-end documents the\n * caller cannot read; the edge-shaped queries have to withhold the same ones,\n * or they become a way to enumerate around that check. Supreme admins read\n * everything, so the per-edge check is skipped for them.\n *\n * The cursor describes where to resume in the underlying unfiltered stream,\n * so it is left as it came. A filtered page is therefore often shorter than\n * the requested limit, and that is the stream continuing rather than a sign\n * it ended.\n */\n private async filterRelationshipEdges<\n TEdge extends { readonly sourceId: string; readonly targetId: string },\n TPage extends { readonly items: ReadonlyArray<TEdge> },\n >(\n page: TPage,\n farEnd: \"sourceId\" | \"targetId\",\n ctx: Context,\n ): Promise<TPage> {\n if (this.authorizationService.isSupremeAdmin(ctx.user?.address)) {\n return page;\n }\n\n const decisions = new Map<string, boolean>();\n const items: TEdge[] = [];\n for (const edge of page.items) {\n const documentId = edge[farEnd];\n let canRead = decisions.get(documentId);\n if (canRead === undefined) {\n canRead = await this.canReadDocument(\n documentId as CanonicalDocumentId,\n ctx,\n );\n decisions.set(documentId, canRead);\n }\n if (canRead) {\n items.push(edge);\n }\n }\n\n return { ...page, items };\n }\n\n /**\n * Adds to `forbidden` the canonical document ids in `syncOps` that the caller\n * cannot read, checking each distinct id once. Sync operation document ids are\n * canonical (never slugs), so no resolution is needed.\n */\n async #collectForbiddenDocuments(\n syncOps: ReadonlyArray<{ documentId: string }>,\n forbidden: Set<string>,\n ctx: Context,\n ): Promise<void> {\n const checked = new Set<string>();\n for (const syncOp of syncOps) {\n const documentId = syncOp.documentId;\n if (checked.has(documentId) || forbidden.has(documentId)) continue;\n checked.add(documentId);\n const canRead = await this.canReadDocument(\n documentId as CanonicalDocumentId,\n ctx,\n );\n if (!canRead) forbidden.add(documentId);\n }\n }\n\n /**\n * Enforces which subject a sync channel answers to, adopting an unclaimed one.\n *\n * A channel is a private queue: it names a collection, and it accumulates\n * exactly the operations one subject is owed, so serving it to a second\n * subject would hand over that subject's cursor as well as its contents. An\n * unbound channel -- created anonymously, or created before binding existed --\n * is claimed by the first authenticated subject to use it, and answers to that\n * address alone thereafter. Adoption is safe precisely because serving\n * withholds rather than consumes: before it was claimed the channel served\n * only what an anonymous subject may read, and everything withheld is still\n * queued for the adopter.\n *\n * The refusal is the shape a read denial takes, so a puller treats it as a\n * signal to authenticate again rather than as a transport failure. Pushes are\n * refused the same way -- a push interacts with the same private queue, and\n * reports the liveness that keeps it from being reclaimed -- but they never\n * adopt, since the push path has no drive check to clear the claimant.\n *\n * Nothing is enforced or adopted without a serving gate: with no gate the\n * channel serves every subject alike, so there is no subject for it to\n * belong to.\n */\n async #bindOrRefuseChannel(\n channelId: string,\n ctx: Context,\n options: { adopt?: boolean; action?: \"poll\" | \"push to\" } = {},\n ): Promise<void> {\n if (!this.syncServingGate) return;\n\n // Claiming a channel is a write, so only a caller the coarse drive check\n // has already cleared may do it. The push path has no such check and asks\n // for refusal alone, or any authenticated address could claim a channel it\n // can never poll and lock its rightful owner out for good.\n const { adopt = true, action = \"poll\" } = options;\n\n let remote;\n try {\n remote = this.syncManager.getById(channelId);\n } catch {\n // Not registered yet: touchChannel is about to create it, bound to its\n // creator.\n return;\n }\n\n const bound = remote.meta.options.boundAddress;\n const address = ctx.user?.address;\n\n if (bound === undefined) {\n if (adopt && address !== undefined) {\n await this.syncManager.bindRemote(channelId, address);\n }\n return;\n }\n\n if (bound !== address) {\n throw new ForbiddenError(`to ${action} this sync channel`);\n }\n }\n\n /** The address a channel created by this request belongs to, if any. */\n #creatorBinding(ctx: Context): string | undefined {\n return this.syncServingGate ? ctx.user?.address : undefined;\n }\n\n typeDefs = gql(schemaSource);\n\n resolvers: Resolvers = {\n // Field resolver for PHDocument.operations - fetches operations on demand\n PHDocument: {\n operations: async (parent, args, ctx: Context) => {\n this.logger.debug(\n \"PHDocument.operations(@parent.id, @args)\",\n parent.id,\n args,\n );\n\n await this.assertCanReadCanonical(\n parent.id as CanonicalDocumentId,\n ctx,\n );\n\n try {\n // Build the filter using the document's id\n const filter = {\n documentId: parent.id,\n branch: args.filter?.branch,\n scopes: args.filter?.scopes,\n actionTypes: args.filter?.actionTypes,\n sinceRevision: args.filter?.sinceRevision,\n timestampFrom: args.filter?.timestampFrom,\n timestampTo: args.filter?.timestampTo,\n };\n\n return await resolvers.documentOperations(\n this.reactorClient,\n { filter, paging: args.paging },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\"Error in PHDocument.operations: @Error\", error);\n throw error;\n }\n },\n },\n\n Query: {\n documentModels: async (_parent, args) => {\n this.logger.debug(\"documentModels(@args)\", args);\n try {\n return await resolvers.documentModels(this.reactorClient, args);\n } catch (error) {\n this.logger.error(\"Error in documentModels: @Error\", error);\n throw error;\n }\n },\n\n document: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"document(@args)\", args);\n try {\n const handle = await this.assertCanRead(args.identifier, ctx);\n return await resolvers.document(\n this.reactorClient,\n { ...args, identifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\"Error in document: @Error\", error);\n throw error;\n }\n },\n\n documentOutgoingRelationships: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"documentOutgoingRelationships(@args)\", args);\n try {\n const handle = await this.assertCanRead(args.sourceIdentifier, ctx);\n return await resolvers.documentOutgoingRelationships(\n this.reactorClient,\n { ...args, sourceIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in documentOutgoingRelationships: @Error\",\n error,\n );\n throw error;\n }\n },\n\n documentIncomingRelationships: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"documentIncomingRelationships(@args)\", args);\n try {\n const handle = await this.assertCanRead(args.targetIdentifier, ctx);\n const result = await resolvers.documentIncomingRelationships(\n this.reactorClient,\n { ...args, targetIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n if (!this.authorizationService.isSupremeAdmin(ctx.user?.address)) {\n const filteredItems = [];\n for (const item of result.items) {\n const canRead = await this.canReadDocument(\n item.id as CanonicalDocumentId,\n ctx,\n );\n if (canRead) {\n filteredItems.push(item);\n }\n }\n return { ...result, items: filteredItems };\n }\n\n return result;\n } catch (error) {\n this.logger.error(\n \"Error in documentIncomingRelationships: @Error\",\n error,\n );\n throw error;\n }\n },\n\n documentOutgoingRelationshipEdges: async (\n _parent,\n args,\n ctx: Context,\n ) => {\n this.logger.debug(\"documentOutgoingRelationshipEdges(@args)\", args);\n try {\n const handle = await this.assertCanRead(args.sourceIdentifier, ctx);\n const result = await resolvers.documentOutgoingRelationshipEdges(\n this.reactorClient,\n { ...args, sourceIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n return await this.filterRelationshipEdges(result, \"targetId\", ctx);\n } catch (error) {\n this.logger.error(\n \"Error in documentOutgoingRelationshipEdges: @Error\",\n error,\n );\n throw error;\n }\n },\n\n documentIncomingRelationshipEdges: async (\n _parent,\n args,\n ctx: Context,\n ) => {\n this.logger.debug(\"documentIncomingRelationshipEdges(@args)\", args);\n try {\n const handle = await this.assertCanRead(args.targetIdentifier, ctx);\n const result = await resolvers.documentIncomingRelationshipEdges(\n this.reactorClient,\n { ...args, targetIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n return await this.filterRelationshipEdges(result, \"sourceId\", ctx);\n } catch (error) {\n this.logger.error(\n \"Error in documentIncomingRelationshipEdges: @Error\",\n error,\n );\n throw error;\n }\n },\n\n findDocuments: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"findDocuments(@args)\", args);\n try {\n const result = await resolvers.findDocuments(\n this.reactorClient,\n { ...args, search: args.search ?? {} },\n this.viewSubject(ctx),\n );\n\n // Filter results to only include documents the user can read\n if (!this.authorizationService.isSupremeAdmin(ctx.user?.address)) {\n const filteredItems = [];\n for (const item of result.items) {\n const canRead = await this.canReadDocument(\n item.id as CanonicalDocumentId,\n ctx,\n );\n if (canRead) {\n filteredItems.push(item);\n }\n }\n return { ...result, items: filteredItems };\n }\n\n return result;\n } catch (error) {\n this.logger.error(\"Error in findDocuments: @Error\", error);\n throw error;\n }\n },\n\n jobStatus: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"jobStatus(@args)\", args);\n try {\n return await resolvers.jobStatus(this.reactorClient, args, (id) =>\n this.servesDocument(id, ctx),\n );\n } catch (error) {\n this.logger.error(\"Error in jobStatus: @Error\", error);\n throw error;\n }\n },\n\n documentOperations: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"documentOperations(@args)\", args);\n try {\n const handle = await this.assertCanRead(args.filter.documentId, ctx);\n return await resolvers.documentOperations(\n this.reactorClient,\n {\n ...args,\n filter: {\n ...args.filter,\n documentId: handle.fetchIdentifier,\n },\n },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\"Error in documentOperations: @Error\", error);\n throw error;\n }\n },\n\n /**\n * Gated on reading the document, the same gate every other read here\n * carries: a verdict is derived from the document's policy, so a caller\n * who may not read the document may not preflight against it either.\n * That gate decides whether the query runs; the answer comes entirely\n * from the reactor's decision model.\n */\n evaluateActions: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"evaluateActions(@args)\", args);\n try {\n const handle = await this.assertCanRead(args.documentIdentifier, ctx);\n return await resolvers.evaluateActions(\n this.reactorClient,\n { ...args, documentIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\"Error in evaluateActions: @Error\", error);\n throw error;\n }\n },\n\n pollSyncEnvelopes: async (\n _parent: unknown,\n args: { channelId: string; outboxAck: number; outboxLatest: number },\n ctx: Context,\n ) => {\n this.logger.debug(\"pollSyncEnvelopes(@args)\", args);\n\n try {\n let remote;\n try {\n remote = this.syncManager.getById(args.channelId);\n } catch (error) {\n throw new GraphQLError(\n `Channel not found: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // A collection is a drive-level abstraction; its canonical drive id is\n // carried by the collection id (never a slug).\n const driveId = remote.meta.collectionId\n .driveId as CanonicalDocumentId;\n const isAdmin = this.authorizationService.isSupremeAdmin(\n ctx.user?.address,\n );\n\n // Tier 1: reading any operation in a collection requires read access to\n // the drive it belongs to. No drive read, no document read.\n if (!isAdmin) {\n await this.assertCanReadCanonical(driveId, ctx);\n }\n\n // Adoption is a write, so it comes after the drive check: a caller\n // this collection refuses must not claim the channel on its way out.\n // `bindRemote` will not rebind, so a stray claim would lock the\n // rightful owner out for good. touchChannel orders these the same way.\n await this.#bindOrRefuseChannel(args.channelId, ctx);\n\n // Tier 2/3: drop operations and dead letters for documents the caller\n // cannot read individually.\n const forbiddenIds = new Set<string>();\n if (!isAdmin) {\n // A caller who can read a *protected* drive holds a grant that\n // inherits to every in-collection member, so the outbox needs no\n // per-document check. Only a world-readable drive can contain an\n // individually-protected member this caller cannot read.\n const driveWorldReadable = await this.authorizationService.canRead(\n driveId,\n undefined,\n );\n if (driveWorldReadable) {\n await this.#collectForbiddenDocuments(\n remote.channel.outbox.items,\n forbiddenIds,\n ctx,\n );\n }\n // Dead letters can carry documents outside this collection (failed\n // inbox jobs) that the drive gate does not cover, so always filter.\n await this.#collectForbiddenDocuments(\n remote.channel.deadLetter.items,\n forbiddenIds,\n ctx,\n );\n }\n\n // Tier 2/3 again, from the document's own policy this time. The two\n // verdicts are intersected rather than swapped: every document\n // predating the policy migration reads as uninitialized, so trusting\n // the policy alone would open whatever the host's tables still\n // protect. Held entries are withheld, not consumed, so a grant that\n // widens later serves them whole on the next poll.\n // One snapshot feeds both the gate and the poll. Re-reading the\n // outbox after the gate's awaits would let an entry queued in the\n // meantime through with no verdict attached to it.\n const gate = this.syncServingGate;\n const gated = gate\n ? [\n ...remote.channel.outbox.items,\n ...remote.channel.deadLetter.items,\n ]\n : undefined;\n const heldOpIds =\n gate && gated\n ? await resolvers.collectHeldSyncOperations(\n gated,\n gate,\n this.viewSubject(ctx),\n )\n : new Set<string>();\n\n const { envelopes, ackOrdinal, deadLetters, hasMore } =\n resolvers.pollSyncEnvelopes(\n this.syncManager,\n args,\n forbiddenIds,\n heldOpIds,\n gated && new Set(gated.map((syncOp) => syncOp.id)),\n );\n return {\n envelopes,\n ackOrdinal,\n deadLetters,\n hasMore,\n };\n } catch (error) {\n this.logger.error(\n \"Error in pollSyncEnvelopes(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n },\n\n Mutation: {\n createDocument: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"createDocument(@args)\", args);\n try {\n // If creating under a parent, check write permission on parent\n if (args.parentIdentifier) {\n const parent = await resolvers.document(this.reactorClient, {\n identifier: args.parentIdentifier,\n });\n\n await this.assertCanWriteCanonical(\n parent.document.id as CanonicalDocumentId,\n ctx,\n );\n } else {\n this.assertCanCreate(ctx);\n }\n const result = await resolvers.createDocument(\n this.reactorClient,\n args,\n this.graphqlManager.reactorDriveClient,\n this.viewSubject(ctx),\n );\n\n if (result?.id && isDriveContainerType(result.documentType)) {\n this.graphqlManager.driveOwnershipCache.add(result.id);\n }\n\n // Auto-ownership: set creator as document owner\n if (ctx.user?.address && result?.id) {\n await this.documentPermissionService?.initializeDocumentProtection(\n result.id,\n ctx.user.address,\n this.authorizationService.config.defaultProtection,\n );\n }\n\n return result;\n } catch (error) {\n this.logger.error(\n \"Error in createDocument(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n createEmptyDocument: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"createEmptyDocument(@args)\", args);\n try {\n // If creating under a parent, check write permission on parent\n if (args.parentIdentifier) {\n const parent = await resolvers.document(this.reactorClient, {\n identifier: args.parentIdentifier,\n });\n\n await this.assertCanWriteCanonical(\n parent.document.id as CanonicalDocumentId,\n ctx,\n );\n } else {\n this.assertCanCreate(ctx);\n }\n const result = await resolvers.createEmptyDocument(\n this.reactorClient,\n args,\n this.graphqlManager.reactorDriveClient,\n this.viewSubject(ctx),\n );\n\n if (result?.id && isDriveContainerType(result.documentType)) {\n this.graphqlManager.driveOwnershipCache.add(result.id);\n }\n\n // Auto-ownership: set creator as document owner\n if (ctx.user?.address && result?.id) {\n await this.documentPermissionService?.initializeDocumentProtection(\n result.id,\n ctx.user.address,\n this.authorizationService.config.defaultProtection,\n );\n }\n\n return result;\n } catch (error) {\n this.logger.error(\n \"Error in createEmptyDocument(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n execute: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"execute(@args)\", args);\n try {\n // canMutate combines the write + operation checks per action.\n const handle = await this.assertCanExecuteOperations(\n args.documentIdentifier,\n args.actions,\n ctx,\n );\n\n return await resolvers.execute(\n this.reactorClient,\n { ...args, documentIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\"Error in execute(@args): @Error\", args, error);\n throw error;\n }\n },\n\n executeAsync: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"executeAsync(@args)\", args);\n try {\n const handle = await this.assertCanExecuteOperations(\n args.documentIdentifier,\n args.actions,\n ctx,\n );\n\n return await resolvers.executeAsync(this.reactorClient, {\n ...args,\n documentIdentifier: handle.fetchIdentifier,\n });\n } catch (error) {\n this.logger.error(\n \"Error in executeAsync(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n mutateDocument: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"mutateDocument(@args)\", args);\n try {\n // canMutate combines the write + operation checks per action.\n const handle = await this.assertCanExecuteOperations(\n args.documentIdentifier,\n args.actions,\n ctx,\n );\n\n return await resolvers.mutateDocument(\n this.reactorClient,\n { ...args, documentIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in mutateDocument(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n mutateDocumentAsync: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"mutateDocumentAsync(@args)\", args);\n try {\n const handle = await this.assertCanExecuteOperations(\n args.documentIdentifier,\n args.actions,\n ctx,\n );\n\n return await resolvers.mutateDocumentAsync(this.reactorClient, {\n ...args,\n documentIdentifier: handle.fetchIdentifier,\n });\n } catch (error) {\n this.logger.error(\n \"Error in mutateDocumentAsync(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n renameDocument: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"renameDocument(@args)\", args);\n try {\n const handle = await this.assertCanWrite(\n args.documentIdentifier,\n ctx,\n );\n\n return await resolvers.renameDocument(\n this.reactorClient,\n { ...args, documentIdentifier: handle.fetchIdentifier },\n undefined,\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in renameDocument(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n setPreferredEditor: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"setPreferredEditor(@args)\", args);\n try {\n const handle = await this.assertCanWrite(\n args.documentIdentifier,\n ctx,\n );\n\n return await resolvers.setPreferredEditor(\n this.reactorClient,\n { ...args, documentIdentifier: handle.fetchIdentifier },\n undefined,\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in setPreferredEditor(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n addRelationship: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"addRelationship(@args)\", args);\n try {\n const handle = await this.assertCanWrite(args.sourceIdentifier, ctx);\n\n return await resolvers.addRelationship(\n this.reactorClient,\n { ...args, sourceIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in addRelationship(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n updateRelationship: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"updateRelationship(@args)\", args);\n try {\n const handle = await this.assertCanWrite(args.sourceIdentifier, ctx);\n\n return await resolvers.updateRelationship(\n this.reactorClient,\n { ...args, sourceIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in updateRelationship(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n removeRelationship: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"removeRelationship(@args)\", args);\n try {\n const handle = await this.assertCanWrite(args.sourceIdentifier, ctx);\n\n return await resolvers.removeRelationship(\n this.reactorClient,\n { ...args, sourceIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in removeRelationship(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n moveRelationship: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"moveRelationship(@args)\", args);\n try {\n const sourceHandle = await this.assertCanWrite(\n args.sourceParentIdentifier,\n ctx,\n );\n const targetHandle = await this.assertCanWrite(\n args.targetParentIdentifier,\n ctx,\n );\n\n return await resolvers.moveRelationship(\n this.reactorClient,\n {\n ...args,\n sourceParentIdentifier: sourceHandle.fetchIdentifier,\n targetParentIdentifier: targetHandle.fetchIdentifier,\n },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in moveRelationship(@args): @Error @args\",\n error,\n args,\n );\n throw error;\n }\n },\n\n deleteDocument: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"deleteDocument(@args)\", args);\n try {\n const handle = await this.assertCanWrite(args.identifier, ctx);\n const identifier = handle.fetchIdentifier;\n\n // Resolve identifier (id or slug) to detect drive deletes for cache\n // invalidation. Only one read; no-op for non-drive callers via the\n // catch.\n const driveIdToInvalidate = await this.#resolveDriveId(identifier);\n\n const result = await resolvers.deleteDocument(\n this.reactorClient,\n { ...args, identifier },\n this.graphqlManager.reactorDriveClient,\n );\n\n if (result && driveIdToInvalidate) {\n this.graphqlManager.driveOwnershipCache.remove(driveIdToInvalidate);\n }\n\n return result;\n } catch (error) {\n this.logger.error(\n \"Error in deleteDocument(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n deleteDocuments: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"deleteDocuments(@args)\", args);\n try {\n // Check write permission on each document, resolving slugs so the\n // delete targets the same canonical ids the checks authorized.\n const identifiers: string[] = [];\n for (const identifier of args.identifiers) {\n const handle = await this.assertCanWrite(identifier, ctx);\n identifiers.push(handle.fetchIdentifier);\n }\n return await resolvers.deleteDocuments(this.reactorClient, {\n ...args,\n identifiers,\n });\n } catch (error) {\n this.logger.error(\n \"Error in deleteDocuments(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n touchChannel: async (\n _parent: unknown,\n args: {\n input: {\n id: string;\n name: string;\n collectionId: string;\n filter: {\n documentId: readonly string[];\n scope: readonly string[];\n branch: string;\n };\n sinceTimestampUtcMs: string;\n };\n },\n ctx: Context,\n ) => {\n this.logger.debug(\"touchChannel(@args)\", args);\n\n try {\n // A channel synchronizes a collection, i.e. a drive. Registering one\n // requires read access to that drive; pushed operations are still\n // authorized per-operation in pushSyncEnvelopes. The collection id\n // carries the canonical drive id (never a slug).\n if (!this.authorizationService.isSupremeAdmin(ctx.user?.address)) {\n const driveId = DriveCollectionId.fromKey(args.input.collectionId)\n .driveId as CanonicalDocumentId;\n await this.assertCanReadCanonical(driveId, ctx);\n }\n\n await this.#bindOrRefuseChannel(args.input.id, ctx);\n\n return await resolvers.touchChannel(\n this.syncManager,\n args,\n this.#creatorBinding(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in touchChannel(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n pushSyncEnvelopes: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"pushSyncEnvelopes(@args)\", args);\n\n try {\n // A push claims or proves ownership exactly as a poll does. It has to\n // be checked here rather than left to the per-operation canMutate\n // loop below, because an envelope carrying no operations skips that\n // loop entirely -- and a push stamps channel liveness, so without\n // this anyone who learns a channel id could keep that channel, and\n // the operations it is holding, alive for good.\n const boundChannelIds = new Set<string>();\n for (const envelope of args.envelopes) {\n const channelId = envelope.channelMeta.id;\n if (boundChannelIds.has(channelId)) continue;\n boundChannelIds.add(channelId);\n await this.#bindOrRefuseChannel(channelId, ctx, {\n adopt: false,\n action: \"push to\",\n });\n }\n\n // Check canMutate per distinct (documentId, action type). Nested map\n // rather than a joined key: a separator could be forged to collide\n // two distinct pairs and skip a check.\n const checkedOperations = new Map<string, Set<string>>();\n for (const envelope of args.envelopes) {\n for (const op of envelope.operations ?? []) {\n const documentId = op.context.documentId;\n const operationType = op.operation.action.type;\n let checkedTypes = checkedOperations.get(documentId);\n if (!checkedTypes) {\n checkedTypes = new Set<string>();\n checkedOperations.set(documentId, checkedTypes);\n }\n if (checkedTypes.has(operationType)) continue;\n checkedTypes.add(operationType);\n // Operation context ids are canonical document ids supplied by the\n // sync protocol (never slugs) and may reference documents not yet\n // materialized locally, so check them without slug resolution.\n await this.assertCanExecuteOperationCanonical(\n documentId as CanonicalDocumentId,\n operationType,\n ctx,\n );\n }\n }\n\n // Convert readonly arrays to mutable arrays for the resolver\n const mutableArgs = {\n envelopes: args.envelopes.map((envelope) => ({\n type: envelope.type,\n channelMeta: { id: envelope.channelMeta.id },\n operations: envelope.operations\n ? envelope.operations.map((op) => ({\n operation: op.operation,\n context: {\n documentId: op.context.documentId,\n documentType: op.context.documentType,\n scope: op.context.scope,\n branch: op.context.branch,\n ordinal: op.context.ordinal,\n },\n }))\n : null,\n cursor: envelope.cursor\n ? {\n remoteName: envelope.cursor.remoteName,\n cursorOrdinal: envelope.cursor.cursorOrdinal,\n lastSyncedAtUtcMs: envelope.cursor.lastSyncedAtUtcMs,\n }\n : null,\n key: envelope.key ?? undefined,\n dependsOn: envelope.dependsOn\n ? [...envelope.dependsOn]\n : undefined,\n })),\n };\n\n return await resolvers.pushSyncEnvelopes(\n this.syncManager,\n mutableArgs,\n );\n } catch (error) {\n this.logger.error(\n \"Error in pushSyncEnvelopes(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n },\n\n Subscription: {\n documentChanges: {\n // Each subscriber reads the reactor's feed as its own subject, so the\n // client withholds what the policy refuses it. The predicate adds the\n // host's legacy check; both transports share this resolver.\n subscribe: (\n rootValue: unknown,\n args: {\n search?: { type?: string | null; parentId?: string | null } | null;\n },\n ctx: Context,\n info: unknown,\n ) => {\n this.logger.debug(\"documentChanges subscription started\");\n const filtered = withFilter<\n DocumentChangesPayload,\n {\n search?: {\n type?: string | null;\n parentId?: string | null;\n } | null;\n },\n Context\n >(\n () => this.documentChanges.subscribe(this.viewSubject(ctx)),\n async (payload, filterArgs, filterCtx) => {\n if (!payload) return false;\n\n const search = {\n type: filterArgs?.search?.type ?? undefined,\n parentId: filterArgs?.search?.parentId ?? undefined,\n };\n if (!matchesSearchFilter(payload.documentChanges, search)) {\n return false;\n }\n\n if (\n this.authorizationService.isSupremeAdmin(\n filterCtx?.user?.address,\n )\n ) {\n return true;\n }\n\n const documentIds = collectChangedDocumentIds(\n payload.documentChanges,\n );\n if (documentIds.length === 0) return false;\n for (const documentId of documentIds) {\n const canRead = await this.canReadDocument(\n documentId as CanonicalDocumentId,\n filterCtx as Context,\n );\n if (!canRead) return false;\n }\n return true;\n },\n );\n return filtered(rootValue as DocumentChangesPayload, args, ctx, info);\n },\n resolve: (payload: DocumentChangesPayload) => {\n return toGqlDocumentChangeEvent(payload.documentChanges);\n },\n },\n\n jobChanges: {\n // Drop events unless the subscriber can read the job's document.\n subscribe: (\n rootValue: unknown,\n args: { jobId: string },\n ctx: Context,\n info: unknown,\n ) => {\n this.logger.debug(\"jobChanges(@args) subscription started\", args);\n const filtered = withFilter<\n JobChangesPayload,\n { jobId: string },\n Context\n >(\n () => {\n ensureJobSubscription(this.reactorClient, args.jobId);\n return getPubSub().asyncIterableIterator<JobChangesPayload>(\n SUBSCRIPTION_TRIGGERS.JOB_CHANGES,\n );\n },\n async (payload, filterArgs, filterCtx) => {\n if (!payload || !filterArgs) return false;\n if (!matchesJobFilter(payload, filterArgs)) return false;\n if (\n !(await this.servesDocument(\n payload.documentId,\n filterCtx as Context,\n ))\n ) {\n return false;\n }\n\n if (\n this.authorizationService.isSupremeAdmin(\n filterCtx?.user?.address,\n )\n ) {\n return true;\n }\n\n if (!payload.documentId) return false;\n return this.canReadDocument(\n payload.documentId as CanonicalDocumentId,\n filterCtx as Context,\n );\n },\n );\n return filtered(rootValue as JobChangesPayload, args, ctx, info);\n },\n resolve: (payload: JobChangesPayload) => {\n return payload.jobChanges;\n },\n },\n },\n };\n\n onSetup(): Promise<void> {\n this.logger.debug(\"Setting up ReactorSubgraph\");\n\n return Promise.resolve();\n }\n}\n","export const getAdminUsers = (): string[] => {\n return (\n process.env.ADMIN_USERS?.split(\",\").map((user) =>\n user.trim().toLocaleLowerCase(),\n ) || []\n );\n};\n","import dotenv from \"dotenv\";\nimport { getAdminUsers } from \"./getters.js\";\n\n// `dotenv.config()` reads a .env file relative to `process.cwd()`. This module\n// is pulled in whenever a package's subgraph is loaded, including by the\n// reactor's CDN/edge package loader, whose runtime has no full `process`\n// (`process.cwd` is not a function). Calling it there throws\n// \"process.cwd is not a function\" and aborts package loading. Guard it: only\n// load a .env file in a real Node context — elsewhere env already lives in\n// `process.env`, so there is nothing to load.\nif (typeof process !== \"undefined\" && typeof process.cwd === \"function\") {\n dotenv.config();\n}\n\nexport const ADMIN_USERS = getAdminUsers();\n","import { buildTreeUrl } from \"@powerhousedao/shared\";\n\ndeclare const REACTOR_API_VERSION: string | undefined;\ndeclare const REACTOR_API_GIT_SHA: string | undefined;\n\nexport function getVersion(): string {\n if (typeof REACTOR_API_VERSION !== \"undefined\") return REACTOR_API_VERSION;\n return (\n process.env.WORKSPACE_VERSION ??\n process.env.npm_package_version ??\n \"unknown\"\n );\n}\n\nexport function getGitHash(): string {\n if (typeof REACTOR_API_GIT_SHA !== \"undefined\") return REACTOR_API_GIT_SHA;\n return process.env.WORKSPACE_GIT_SHA ?? \"unknown\";\n}\n\nexport function getGitUrl(): string | null {\n return buildTreeUrl(getGitHash());\n}\n","import { gql } from \"graphql-tag\";\nimport { BaseSubgraph } from \"../base-subgraph.js\";\nimport { getGitHash, getGitUrl, getVersion } from \"./version.js\";\n\nexport class SystemSubgraph extends BaseSubgraph {\n name = \"system\";\n hasSubscriptions = false;\n\n typeDefs = gql`\n type SystemInfo {\n version: String!\n gitHash: String!\n gitUrl: String\n }\n\n type Query {\n system: SystemInfo!\n }\n `;\n\n resolvers = {\n Query: {\n system: () => ({\n version: getVersion(),\n gitHash: getGitHash(),\n gitUrl: getGitUrl(),\n }),\n },\n };\n}\n","import type { IDocumentModelLoader } from \"@powerhousedao/reactor\";\nimport type { SubgraphClass } from \"@powerhousedao/reactor-api\";\nimport type {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport { childLogger } from \"document-model\";\nimport type { IPackageLoader, ProcessorFactoryBuilder } from \"../types.js\";\nimport { piecesFromCdnList } from \"./pieces.js\";\nimport type { PackagePieceEntry } from \"./types.js\";\nimport { extractUpgradeManifests } from \"./util.js\";\n\nexport interface HttpPackageLoaderOptions {\n registryUrl: string;\n}\n\nexport interface HttpPackageLoaderLogger {\n info: (msg: string) => void;\n error: (msg: string, err: unknown) => void;\n}\n\n// Expected shape of the document-models bundle export\ntype DocumentModelsExport = Record<string, DocumentModelModule>;\n\n// Expected shape of the subgraphs bundle export\ntype SubgraphsExport = Record<string, SubgraphClass>;\n\n/**\n * Extract subgraph classes from the imported subgraphs/index.mjs module shape.\n *\n * The published bundle uses `export * as Foo from \"./file\"`, which Node turns\n * into `{ Foo: <namespace>, … }`. The inner namespace's keys come from the\n * source file's named exports — typically `Subgraph` / `default` / the class\n * name itself — so the shape varies. Flatten one level and keep callables.\n *\n * Exported for direct unit testing against synthetic module shapes.\n */\nexport function extractSubgraphsFromModule(\n module: Record<string, SubgraphsExport>,\n): SubgraphClass[] {\n return Object.values(module)\n .flatMap((namespace) => Object.values(namespace))\n .filter((s): s is SubgraphClass => typeof s === \"function\");\n}\n\n// Expected shape of the processors bundle export\ntype ProcessorsExport = {\n processorFactory?: ProcessorFactoryBuilder;\n};\n\n/**\n * Loads document models, subgraphs, and processors from an HTTP registry.\n * Uses Node.js module loader hooks to import directly from HTTP URLs.\n *\n * IMPORTANT: Requires https-hooks to be registered before use:\n * import { register } from \"node:module\";\n * register(\"@powerhousedao/reactor-api/https-hooks\", import.meta.url);\n */\nexport class HttpPackageLoader implements IPackageLoader {\n private readonly registryUrl: string;\n private readonly logger = childLogger([\"reactor-api\", \"http-loader\"]);\n\n readonly name = \"HttpPackageLoader\";\n\n readonly documentModelLoader: HttpDocumentModelLoader;\n\n constructor(options: HttpPackageLoaderOptions) {\n this.registryUrl = options.registryUrl.endsWith(\"/\")\n ? options.registryUrl\n : `${options.registryUrl}/`;\n this.documentModelLoader = new HttpDocumentModelLoader(this);\n }\n\n /**\n * Load document models from a package in the HTTP registry.\n * Imports directly from HTTP URL using Node.js loader hooks.\n */\n /**\n * Parse a package specifier like \"@scope/pkg@tag\" into name and optional tag.\n */\n private parsePackageSpec(spec: string): {\n name: string;\n tag: string | undefined;\n } {\n if (spec.startsWith(\"@\")) {\n const lastAt = spec.lastIndexOf(\"@\");\n if (lastAt > 0 && lastAt !== spec.indexOf(\"@\")) {\n return { name: spec.slice(0, lastAt), tag: spec.slice(lastAt + 1) };\n }\n return { name: spec, tag: undefined };\n }\n const atIndex = spec.indexOf(\"@\");\n if (atIndex > 0) {\n return { name: spec.slice(0, atIndex), tag: spec.slice(atIndex + 1) };\n }\n return { name: spec, tag: undefined };\n }\n\n async loadDocumentModels(\n packageSpec: string,\n ): Promise<DocumentModelModule[]> {\n const { name: packageName } = this.parsePackageSpec(packageSpec);\n if (!this.isValidPackageName(packageName)) {\n throw new Error(`Invalid package name: ${packageName}`);\n }\n\n // Pass the full spec (with tag) to the CDN — the registry resolves it\n const url = `${this.registryUrl}-/cdn/${packageSpec}/node/document-models/index.mjs`;\n\n this.logger.verbose(`Importing document-models from: ${url}`);\n\n // Direct import from HTTP URL - hooks handle the fetch\n const module = (await import(url)) as DocumentModelsExport;\n\n const models = Object.values(module).filter(\n (m: unknown): m is DocumentModelModule =>\n m !== null &&\n typeof m === \"object\" &&\n \"documentModel\" in m &&\n m.documentModel !== null,\n );\n\n this.logger.verbose(\n `Loaded ${models.length} document models from ${packageName}`,\n );\n return models;\n }\n\n async loadUpgradeManifests(\n packageSpec: string,\n ): Promise<UpgradeManifest<readonly number[]>[]> {\n const { name: packageName } = this.parsePackageSpec(packageSpec);\n if (!this.isValidPackageName(packageName)) {\n throw new Error(`Invalid package name: ${packageName}`);\n }\n\n const url = `${this.registryUrl}-/cdn/${packageSpec}/node/document-models/index.mjs`;\n const module = (await import(url)) as Record<string, unknown>;\n\n const manifests = extractUpgradeManifests(module);\n if (manifests.length > 0) {\n this.logger.verbose(\n `Loaded ${manifests.length} upgrade manifests from ${packageName}`,\n );\n }\n return manifests;\n }\n\n async loadSubgraphs(packageSpec: string): Promise<SubgraphClass[]> {\n const { name: packageName } = this.parsePackageSpec(packageSpec);\n if (!this.isValidPackageName(packageName)) {\n throw new Error(`Invalid package name: ${packageName}`);\n }\n\n const url = `${this.registryUrl}-/cdn/${packageSpec}/node/subgraphs/index.mjs`;\n\n this.logger.verbose(`Importing subgraphs from: ${url}`);\n const module = (await import(url)) as Record<string, SubgraphsExport>;\n const subgraphs = extractSubgraphsFromModule(module);\n\n this.logger.verbose(\n `Loaded ${subgraphs.length} subgraphs from ${packageName}`,\n );\n return subgraphs;\n }\n\n async loadProcessors(\n packageSpec: string,\n ): Promise<ProcessorFactoryBuilder | null> {\n const { name: packageName } = this.parsePackageSpec(packageSpec);\n if (!this.isValidPackageName(packageName)) {\n throw new Error(`Invalid package name: ${packageName}`);\n }\n\n const url = `${this.registryUrl}-/cdn/${packageSpec}/node/processors/index.mjs`;\n\n this.logger.verbose(`Importing processors from: ${url}`);\n const module = (await import(url)) as ProcessorsExport;\n\n const factory = module.processorFactory;\n if (factory && typeof factory === \"function\") {\n this.logger.verbose(`Loaded processor factory from ${packageName}`);\n return factory;\n }\n\n this.logger.verbose(`No processor factory found in ${packageName}`);\n return null;\n }\n\n // The same list module every other loader reads, on the CDN path its three\n // siblings already come from. Metadata only: no piece code is fetched here.\n\n // The declared entry is relative to the package root while the CDN serves\n // beneath `dist/`, so this is the only place that can make it absolute.\n async loadPieces(packageSpec: string): Promise<PackagePieceEntry[]> {\n const { name: packageName } = this.parsePackageSpec(packageSpec);\n if (!this.isValidPackageName(packageName)) {\n throw new Error(`Invalid package name: ${packageName}`);\n }\n const base = `${this.registryUrl}-/cdn/${packageSpec}/node/pieces/`;\n this.logger.verbose(`Importing pieces from: ${base}index.mjs`);\n let module: unknown;\n try {\n module = await import(`${base}index.mjs`);\n } catch (error) {\n // A package shipping none has no list to serve, which is the common\n // case rather than a fault.\n this.logger.verbose(`No pieces found for: ${packageName}`, error);\n return [];\n }\n const pieces = piecesFromCdnList(module, base, packageName, this.logger);\n this.logger.verbose(`Loaded ${pieces.length} pieces from ${packageName}`);\n return pieces;\n }\n\n /**\n * Load document models from multiple packages.\n * Continues loading even if some packages fail.\n */\n async loadPackages(\n packageNames: string[],\n logger?: HttpPackageLoaderLogger,\n ): Promise<DocumentModelModule[]> {\n const allModels: DocumentModelModule[] = [];\n\n for (const pkgName of packageNames) {\n const trimmedName = pkgName.trim();\n if (!trimmedName) continue;\n\n try {\n const models = await this.loadDocumentModels(trimmedName);\n allModels.push(...models);\n const logMsg = `Loaded ${models.length} document models from ${trimmedName}`;\n logger?.info(logMsg);\n this.logger.info(logMsg);\n } catch (error) {\n const errMsg = `Failed to load package ${trimmedName}`;\n logger?.error(errMsg, error);\n this.logger.error(errMsg, error);\n // Continue with other packages - don't fail startup\n }\n }\n\n return allModels;\n }\n\n private isValidPackageName(name: string): boolean {\n // npm package name pattern: optional scope + package name\n const pattern = /^(@[a-z0-9][-a-z0-9._]*\\/)?[a-z0-9][-a-z0-9._]*$/i;\n return pattern.test(name) && !name.includes(\"..\") && name.length <= 214;\n }\n}\n\n/**\n * Returns live modules (host-only sources): dynamically loaded models are\n * registered on the host registry but never reach executor worker threads.\n * Making them worker-executable means returning an importable source here\n * (the CDN URL as a package specifier, given process-wide https hooks).\n */\nexport class HttpDocumentModelLoader implements IDocumentModelLoader {\n private readonly loader: HttpPackageLoader;\n private readonly logger = childLogger([\n \"reactor-api\",\n \"http-document-model-loader\",\n ]);\n\n // Cache: documentType -> packageName\n private readonly documentTypeCache = new Map<string, string>();\n\n // Cache: packageName -> DocumentModelModule[]\n private readonly packageModulesCache = new Map<\n string,\n DocumentModelModule[]\n >();\n\n private onModelLoaded?: (model: DocumentModelModule) => void;\n\n constructor(loader: HttpPackageLoader) {\n this.loader = loader;\n }\n\n setOnModelLoaded(callback: (model: DocumentModelModule) => void): void {\n this.onModelLoaded = callback;\n }\n\n clearCache(): void {\n this.documentTypeCache.clear();\n this.packageModulesCache.clear();\n }\n\n async load(documentType: string): Promise<DocumentModelModule> {\n const packageName = await this.findPackageByDocumentType(documentType);\n\n let models: DocumentModelModule[];\n\n const cachedModels = this.packageModulesCache.get(packageName);\n if (cachedModels) {\n models = cachedModels;\n } else {\n models = await this.loader.loadDocumentModels(packageName);\n this.packageModulesCache.set(packageName, models);\n }\n\n const model = models.find(\n (m) => m.documentModel.global.id === documentType,\n );\n\n if (!model) {\n const availableTypes = models.map((m) => m.documentModel.global.id);\n throw new Error(\n `Document model ${documentType} not found in package ${packageName}. ` +\n `Available types: ${availableTypes.join(\", \")}`,\n );\n }\n\n this.logger.info(\n `Loaded document model \"${documentType}\" from package \"${packageName}\"`,\n );\n\n if (this.onModelLoaded) {\n this.onModelLoaded(model);\n }\n\n return model;\n }\n\n private async findPackageByDocumentType(\n documentType: string,\n ): Promise<string> {\n const cached = this.documentTypeCache.get(documentType);\n if (cached) {\n return cached;\n }\n\n const encodedType = encodeURIComponent(documentType);\n const url = `${this.loader[\"registryUrl\"]}packages/by-document-type?type=${encodedType}`;\n\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(\n `Registry query failed for document type ${documentType}: ${response.status} ${response.statusText}`,\n );\n }\n\n const packageNames = (await response.json()) as string[];\n\n if (packageNames.length === 0) {\n throw new Error(\n `No package found containing document type: ${documentType}`,\n );\n }\n\n const packageName = packageNames.sort((a, b) => a.localeCompare(b))[0];\n this.documentTypeCache.set(documentType, packageName);\n\n return packageName;\n }\n\n getLoadedPackages(): string[] {\n return Array.from(this.packageModulesCache.keys());\n }\n\n getPackageModules(packageName: string): DocumentModelModule[] | undefined {\n return this.packageModulesCache.get(packageName);\n }\n\n removeFromCache(packageName: string): void {\n this.packageModulesCache.delete(packageName);\n for (const [docType, pkg] of this.documentTypeCache) {\n if (pkg === packageName) {\n this.documentTypeCache.delete(docType);\n }\n }\n }\n}\n","import type { SubgraphClass } from \"@powerhousedao/reactor-api\";\nimport type {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport { childLogger } from \"document-model\";\nimport { existsSync } from \"node:fs\";\nimport { isAbsolute, join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { IPackageLoader, ProcessorFactoryBuilder } from \"../types.js\";\nimport {\n PIECE_SOURCE_LIST,\n pieceListLocation,\n piecesFromListModule,\n} from \"./pieces.js\";\nimport type { PackagePieceEntry } from \"./types.js\";\nimport {\n extractUpgradeManifests,\n loadDocumentModels as loadDocumentModelsUtil,\n loadProcessors as loadProcessorsUtil,\n loadSubgraphs as loadSubgraphsUtil,\n} from \"./util.js\";\n\n/**\n * This class is used to load packages using the import keyword.\n */\nexport class ImportPackageLoader implements IPackageLoader {\n private readonly logger = childLogger([\"reactor-api\", \"import-loader\"]);\n\n readonly name = \"ImportPackageLoader\";\n\n // Where the host's own dependencies are installed; the process's cwd.\n constructor(private readonly hostDir = process.cwd()) {}\n\n // Said once per package: a project rebuilt while the reactor runs answers\n // on the next load, and repeating the advice every time would only nag.\n private readonly reportedUnbuilt = new Set<string>();\n\n async loadDocumentModels(identifier: string): Promise<DocumentModelModule[]> {\n this.logger.verbose(`Loading document models from package: ${identifier}`);\n\n const pkgModule = await loadDocumentModelsUtil(identifier);\n\n if (pkgModule) {\n // duck type: the namespace also carries non-module exports such as the\n // upgradeManifests aggregate\n const models = Object.values(pkgModule).filter(\n (m: unknown): m is DocumentModelModule =>\n m !== null && typeof m === \"object\" && \"documentModel\" in m,\n );\n this.logger.verbose(\n ` ➜ Loaded ${models.length} Document Models from: ${identifier}`,\n );\n return models;\n } else {\n this.logger.verbose(` ➜ No Document Models found: ${identifier}`);\n return [];\n }\n }\n\n async loadUpgradeManifests(\n identifier: string,\n ): Promise<UpgradeManifest<readonly number[]>[]> {\n const pkgModule = await loadDocumentModelsUtil(identifier);\n if (!pkgModule) return [];\n\n const manifests = extractUpgradeManifests(pkgModule);\n if (manifests.length > 0) {\n this.logger.verbose(\n ` ➜ Loaded ${manifests.length} Upgrade Manifests from: ${identifier}`,\n );\n }\n return manifests;\n }\n\n async loadSubgraphs(identifier: string): Promise<SubgraphClass[]> {\n this.logger.verbose(`Loading subgraphs from package: ${identifier}`);\n\n const pkgModule = await loadSubgraphsUtil(identifier);\n\n if (!pkgModule) {\n this.logger.verbose(` ➜ No Subgraphs found: ${identifier}`);\n\n return [];\n }\n\n const subgraphs = Object.values(pkgModule).map((subgraph) => {\n return Object.values(subgraph);\n });\n\n this.logger.verbose(` ➜ Loaded Subgraphs from: ${identifier}`);\n\n return subgraphs.flat();\n }\n\n async loadProcessors(\n identifier: string,\n ): Promise<ProcessorFactoryBuilder | null> {\n this.logger.verbose(`Loading processors from package: ${identifier}`);\n\n const pkgModule = await loadProcessorsUtil(identifier);\n\n const factory = pkgModule?.processorFactory;\n\n if (factory && typeof factory === \"function\") {\n this.logger.verbose(` ➜ Loaded Processor Factory from: ${identifier}`);\n return factory;\n }\n\n this.logger.verbose(` ➜ No Processor Factory found: ${identifier}`);\n return null;\n }\n\n // Only the list is imported, never a piece: the list is data, and a piece is\n // code that belongs in a worker under an egress policy.\n async loadPieces(identifier: string): Promise<PackagePieceEntry[]> {\n this.logger.verbose(`Loading pieces from package: ${identifier}`);\n\n // A name is left to throw, so the manager can read the resolution error's\n // shape; a path answers for itself, and an absent list means none.\n const { root, listPath } = pieceListLocation(identifier, this.hostDir);\n if (!existsSync(listPath)) {\n this.reportUnbuilt(identifier, root, listPath);\n return [];\n }\n\n const module: unknown = await import(\n /* @vite-ignore */ pathToFileURL(listPath).href\n );\n const pieces = piecesFromListModule(module, {\n root,\n identifier,\n logger: this.logger,\n });\n this.logger.verbose(\n ` ➜ Loaded ${pieces.length} Pieces from: ${identifier}`,\n );\n return pieces;\n }\n\n // A package with piece sources and no built list is half-built, which is a\n // different thing from one that ships no pieces and worth saying so.\n private reportUnbuilt(identifier: string, root: string, listPath: string) {\n if (!isAbsolute(identifier) || this.reportedUnbuilt.has(identifier)) return;\n if (!existsSync(join(root, PIECE_SOURCE_LIST))) return;\n this.reportedUnbuilt.add(identifier);\n this.logger.warn(\n \"@pkg declares pieces but @list was never built; run `ph build`\",\n identifier,\n listPath,\n );\n }\n}\n","import { getConfig } from \"@powerhousedao/config/node\";\nimport type {\n Processor,\n ProcessorFactoryBuilder,\n SubgraphClass,\n} from \"@powerhousedao/reactor-api\";\nimport { reactorDriveDocumentModelModule } from \"@powerhousedao/reactor-drive\";\nimport { ReactorGroupV1 } from \"@powerhousedao/reactor-group\";\nimport { driveDocumentModelModule } from \"@powerhousedao/shared/document-drive\";\nimport type {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport { childLogger, documentModelDocumentModelModule } from \"document-model\";\nimport EventEmitter from \"node:events\";\nimport type { StatWatcher } from \"node:fs\";\nimport { watchFile } from \"node:fs\";\nimport type {\n IPackageLoader,\n IPackageManager,\n IPackageManagerOptions,\n ISubscribablePackageLoader,\n PackageManagerResult,\n PackagePieceEntry,\n} from \"./types.js\";\nimport { debounce } from \"./util.js\";\n\n/**\n * A loader throwing \"this package isn't mine to load\" is normal — loaders are\n * fallbacks for each other. These shapes mean \"not found here\", not \"broken\".\n *\n * `ERR_MODULE_NOT_FOUND` is ambiguous: it can mean either (a) the loader's own\n * entry import for `pkg` failed (expected — the package isn't installed\n * locally), or (b) the entry loaded successfully but a *transitive* bare\n * import inside it couldn't resolve (real error — the bundle is broken). We\n * distinguish by checking whether the error names the package we asked for —\n * either bare (`'pkg'`) or as a subpath (`'pkg/subgraphs'`), since loaders\n * import sub-entries like `${pkg}/subgraphs` / `${pkg}/document-models`.\n */\n// `subPath` is the sub-entry that was asked for. With it, two more answers\n// read as misses: an `exports` map that omits it, and a 404 for it.\nexport function isExpectedLoaderMiss(\n error: unknown,\n pkg: string,\n subPath?: string,\n): boolean {\n if (!(error instanceof Error)) return false;\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"ERR_UNSUPPORTED_DIR_IMPORT\") return true; // empty subgraphs/ etc.\n // An `exports` map without this subpath is the package saying it ships none\n // — the same answer as a missing directory, in a package that declares one.\n if (\n code === \"ERR_PACKAGE_PATH_NOT_EXPORTED\" &&\n subPath !== undefined &&\n error.message.includes(`'./${subPath}'`)\n ) {\n return true;\n }\n // Nothing published at that subpath; any other status is a registry fault,\n // and a 404 naming anything else is a broken bundle, not a miss.\n if (\n subPath !== undefined &&\n new RegExp(`^Failed to fetch \\\\S*/${subPath}/index\\\\.mjs: 404$`).test(\n error.message,\n )\n ) {\n return true;\n }\n // HttpPackageLoader rejects local paths and invalid npm names before any fetch\n if (error.message.startsWith(\"Invalid package name:\")) return true;\n if (code === \"ERR_MODULE_NOT_FOUND\") {\n // Match `'pkg'`, `\"pkg\"`, `'pkg/...'`, or `\"pkg/...\"`. Anything else is a\n // transitive resolution failure inside a successfully-fetched bundle.\n return (\n error.message.includes(`'${pkg}'`) ||\n error.message.includes(`\"${pkg}\"`) ||\n error.message.includes(`'${pkg}/`) ||\n error.message.includes(`\"${pkg}/`)\n );\n }\n return false;\n}\n\nexport function getUniqueDocumentModels(\n ...documentModels: readonly (readonly DocumentModelModule<any>[])[]\n): DocumentModelModule[] {\n const uniqueModels = new Map<string, DocumentModelModule>();\n\n for (const models of documentModels) {\n for (const model of models) {\n // versions of a document type are distinct modules; keying by type\n // alone would keep only the last version of a versioned model\n uniqueModels.set(\n `${model.documentModel.global.id}@${model.version ?? 1}`,\n model,\n );\n }\n }\n\n return Array.from(uniqueModels.values());\n}\n\nexport function getUniqueUpgradeManifests(\n ...upgradeManifests: readonly (readonly UpgradeManifest<\n readonly number[]\n >[])[]\n): UpgradeManifest<readonly number[]>[] {\n const uniqueManifests = new Map<string, UpgradeManifest<readonly number[]>>();\n\n for (const manifests of upgradeManifests) {\n for (const manifest of manifests) {\n uniqueManifests.set(manifest.documentType, manifest);\n }\n }\n\n return Array.from(uniqueManifests.values());\n}\n\nexport class PackageManager implements IPackageManager {\n private readonly logger = childLogger([\"reactor-api\", \"package-manager\"]);\n private loaders: ISubscribablePackageLoader[];\n\n private docModelsMap = new Map<string, DocumentModelModule[]>();\n private upgradeManifestsMap = new Map<\n string,\n UpgradeManifest<readonly number[]>[]\n >();\n private subgraphsMap = new Map<string, SubgraphClass[]>();\n private processorMap = new Map<string, Processor>();\n private piecesMap = new Map<string, PackagePieceEntry[]>();\n private configWatcher: StatWatcher | undefined;\n private debouncedUpdateCallbacks = new Map<string, () => void>();\n private eventEmitter = new EventEmitter<{\n documentModelsChange: [Record<string, DocumentModelModule[]>];\n subgraphsChange: [Map<string, SubgraphClass[]>];\n processorsChange: [Map<string, Processor>];\n piecesChange: [Map<string, PackagePieceEntry[]>];\n }>();\n\n constructor(\n loaders: IPackageLoader[],\n protected options: IPackageManagerOptions,\n ) {\n this.loaders = loaders;\n this.eventEmitter.setMaxListeners(0);\n }\n\n public async init(): Promise<PackageManagerResult> {\n if (this.options.configFile) {\n this.initConfigFileWatcher(this.options.configFile);\n }\n\n return await this.loadPackages(this.getAllPackageNames());\n }\n\n private async loadPackages(\n packages: string[],\n ): Promise<PackageManagerResult> {\n this.logger.info(\"Loading packages: @packages\", packages.join(\", \"));\n\n const documentModelsMap = await this.loadDocumentModels(packages);\n const upgradeManifestsMap = await this.loadUpgradeManifests(packages);\n const subgraphsMap = await this.loadSubgraphs(packages);\n const processorsMap = await this.loadProcessors(packages);\n const piecesMap = await this.loadPieces(packages);\n\n this.upgradeManifestsMap = upgradeManifestsMap;\n this.updatePackagesMap(documentModelsMap);\n this.updateSubgraphsMap(subgraphsMap);\n this.updateProcessorsMap(processorsMap);\n this.updatePiecesMap(piecesMap);\n\n try {\n this.subscribePackages(packages);\n } catch (error) {\n this.logger.error(\"Failed to subscribe to packages: @error\", error);\n }\n\n return {\n documentModels: getUniqueDocumentModels(\n ...Array.from(documentModelsMap.values()),\n ),\n upgradeManifests: this.getUniqueUpgradeManifests(),\n subgraphs: subgraphsMap,\n processors: processorsMap,\n pieces: piecesMap,\n };\n }\n\n private async loadDocumentModels(\n packages: string[],\n ): Promise<Map<string, DocumentModelModule[]>> {\n this.logger.debug(\n `Loading document models from packages: ${packages.join(\", \")}`,\n );\n\n const documentModelModuleMap = new Map<string, DocumentModelModule[]>();\n\n // static prereqs\n documentModelModuleMap.set(\"document-drive\", [\n driveDocumentModelModule as unknown as DocumentModelModule,\n ]);\n\n documentModelModuleMap.set(\"document-model\", [\n documentModelDocumentModelModule as unknown as DocumentModelModule,\n ]);\n\n documentModelModuleMap.set(\"reactor-drive\", [\n reactorDriveDocumentModelModule as unknown as DocumentModelModule,\n ]);\n\n documentModelModuleMap.set(\"reactor-group\", [\n ReactorGroupV1 as unknown as DocumentModelModule,\n ]);\n\n for (const pkg of packages) {\n const allDocumentModels: DocumentModelModule[] = [];\n const failures: { loader: string; error: unknown }[] = [];\n let succeeded = false;\n\n for (const loader of this.loaders) {\n try {\n const documentModels = await loader.loadDocumentModels(pkg);\n\n allDocumentModels.push(...documentModels);\n this.logger.info(\n `[${loader.name}] Loaded document models from package @pkg: @documentModels`,\n pkg,\n documentModels.map((dm) => dm.documentModel.global.id),\n );\n succeeded = true;\n break;\n } catch (error) {\n failures.push({ loader: loader.name, error });\n this.logger.debug(\n `[${loader.name}] Failed to load document models from package @pkg: @error`,\n pkg,\n error,\n );\n }\n }\n\n this.maybeWarnAllLoadersFailed(\n \"document models\",\n pkg,\n succeeded,\n failures,\n );\n\n documentModelModuleMap.set(pkg, allDocumentModels);\n }\n\n return documentModelModuleMap;\n }\n\n /** Upgrade manifests currently loaded across all packages, one per type. */\n public getUniqueUpgradeManifests(): UpgradeManifest<readonly number[]>[] {\n return getUniqueUpgradeManifests(\n ...Array.from(this.upgradeManifestsMap.values()),\n );\n }\n\n private async loadUpgradeManifests(\n packages: string[],\n ): Promise<Map<string, UpgradeManifest<readonly number[]>[]>> {\n const manifestsMap = new Map<\n string,\n UpgradeManifest<readonly number[]>[]\n >();\n\n for (const pkg of packages) {\n for (const loader of this.loaders) {\n if (!loader.loadUpgradeManifests) continue;\n try {\n const manifests = await loader.loadUpgradeManifests(pkg);\n if (manifests.length > 0) {\n manifestsMap.set(pkg, manifests);\n break;\n }\n } catch (error) {\n this.logger.debug(\n `[${loader.name}] Failed to load upgrade manifests from package @pkg: @error`,\n pkg,\n error,\n );\n }\n }\n }\n\n return manifestsMap;\n }\n\n private async loadSubgraphs(\n packages: string[],\n ): Promise<Map<string, SubgraphClass[]>> {\n this.logger.debug(\n `Loading subgraphs from packages: ${packages.join(\", \")}`,\n );\n\n const subgraphsMap = new Map<string, SubgraphClass[]>();\n\n for (const pkg of packages) {\n const allSubgraphs: SubgraphClass[] = [];\n const failures: { loader: string; error: unknown }[] = [];\n let succeeded = false;\n\n for (const loader of this.loaders) {\n try {\n const subgraphs = await loader.loadSubgraphs(pkg);\n\n allSubgraphs.push(...subgraphs);\n succeeded = true;\n break;\n } catch (error) {\n failures.push({ loader: loader.name, error });\n this.logger.debug(\n `[${loader.name}] Failed to load subgraphs from package ${pkg}`,\n error,\n );\n }\n }\n\n this.maybeWarnAllLoadersFailed(\"subgraphs\", pkg, succeeded, failures);\n\n subgraphsMap.set(pkg, allSubgraphs);\n }\n\n return subgraphsMap;\n }\n\n private async loadProcessors(\n packages: string[],\n ): Promise<Map<string, Processor>> {\n this.logger.debug(\n `Loading processors from packages: ${packages.join(\", \")}`,\n );\n\n const processorsMap = new Map<string, Processor>();\n\n for (const pkg of packages) {\n const allProcessors: ProcessorFactoryBuilder[] = [];\n const failures: { loader: string; error: unknown }[] = [];\n let succeeded = false;\n\n for (const loader of this.loaders) {\n try {\n const processors = await loader.loadProcessors(pkg);\n\n if (processors) {\n allProcessors.push(processors);\n }\n succeeded = true;\n break;\n } catch (error) {\n failures.push({ loader: loader.name, error });\n this.logger.debug(\n `[${loader.name}] Failed to load processors from package ${pkg}`,\n error,\n );\n }\n }\n\n this.maybeWarnAllLoadersFailed(\"processors\", pkg, succeeded, failures);\n\n processorsMap.set(pkg, allProcessors);\n }\n\n return processorsMap;\n }\n\n // Paths, not modules: a piece is code the host must not import, and what a\n // worker needs from here is where on disk the package put it.\n private async loadPieces(\n packages: string[],\n ): Promise<Map<string, PackagePieceEntry[]>> {\n this.logger.debug(`Loading pieces from packages: ${packages.join(\", \")}`);\n\n const piecesMap = new Map<string, PackagePieceEntry[]>();\n\n for (const pkg of packages) {\n const allPieces: PackagePieceEntry[] = [];\n const failures: { loader: string; error: unknown }[] = [];\n let succeeded = false;\n\n for (const loader of this.loaders) {\n try {\n allPieces.push(...(await loader.loadPieces(pkg)));\n succeeded = true;\n break;\n } catch (error) {\n failures.push({ loader: loader.name, error });\n this.logger.debug(\n `[${loader.name}] Failed to load pieces from package ${pkg}`,\n error,\n );\n }\n }\n\n this.maybeWarnAllLoadersFailed(\"pieces\", pkg, succeeded, failures);\n\n if (allPieces.length > 0) {\n this.logger.info(\n \"Loaded @count piece(s) from package @pkg: @pieces\",\n allPieces.length,\n pkg,\n allPieces.map((piece) => piece.name).join(\", \"),\n );\n }\n piecesMap.set(pkg, allPieces);\n }\n\n return piecesMap;\n }\n\n private maybeWarnAllLoadersFailed(\n kind: \"document models\" | \"subgraphs\" | \"processors\" | \"pieces\",\n pkg: string,\n succeeded: boolean,\n failures: { loader: string; error: unknown }[],\n ): void {\n if (succeeded || failures.length === 0) return;\n // The package subpath every loader asked for, which is what tells a\n // package that ships none of this kind from one whose bundle is broken.\n const subPath = kind === \"document models\" ? \"document-models\" : kind;\n // Each loader's \"this package isn't mine\" failure is expected fallthrough,\n // not a real error. Only surface a warning when at least one loader hit\n // something unexpected (e.g. a bundle evaluation error or registry 5xx),\n // and show only those non-expected failures — expected misses would just\n // mislead the reader about which loader actually broke.\n const realFailures = failures.filter(\n ({ error }) => !isExpectedLoaderMiss(error, pkg, subPath),\n );\n if (realFailures.length === 0) return;\n\n const details = realFailures\n .map(({ loader, error }) => {\n const message = error instanceof Error ? error.message : String(error);\n return ` [${loader}] ${message}`;\n })\n .join(\"\\n\");\n this.logger.warn(\n `All package loaders failed to load ${kind} from @pkg:\\n@details`,\n pkg,\n details,\n );\n }\n\n private async updateDocumentModelsForPackage(pkg: string): Promise<void> {\n this.logger.debug(`Updating document models for package: ${pkg}`);\n const documentModels = await this.loadDocumentModels([pkg]);\n const upgradeManifests = await this.loadUpgradeManifests([pkg]);\n const upgradeManifestsMap = new Map(this.upgradeManifestsMap);\n const pkgManifests = upgradeManifests.get(pkg) ?? [];\n if (pkgManifests.length === 0) {\n upgradeManifestsMap.delete(pkg);\n } else {\n upgradeManifestsMap.set(pkg, pkgManifests);\n }\n this.upgradeManifestsMap = upgradeManifestsMap;\n const documentModelsMap = new Map(this.docModelsMap);\n const pkgModels = documentModels.get(pkg) ?? [];\n if (pkgModels.length === 0) {\n // An empty result means the package no longer contributes document\n // models: drop the key so the change event signals removal instead of\n // re-asserting an empty entry.\n documentModelsMap.delete(pkg);\n } else {\n documentModelsMap.set(pkg, pkgModels);\n }\n this.updatePackagesMap(documentModelsMap);\n }\n\n private async updateSubgraphsForPackage(pkg: string): Promise<void> {\n this.logger.debug(`Updating subgraphs for package: ${pkg}`);\n const subgraphs = await this.loadSubgraphs([pkg]);\n const subgraphsMap = new Map(this.subgraphsMap);\n const pkgSubgraphs = subgraphs.get(pkg) ?? [];\n if (pkgSubgraphs.length === 0) {\n // An empty result means the package no longer contributes subgraphs\n // (e.g. its subgraphs/ entry was removed): drop the key so the change\n // event signals removal instead of re-asserting an empty entry.\n subgraphsMap.delete(pkg);\n } else {\n subgraphsMap.set(pkg, pkgSubgraphs);\n }\n this.updateSubgraphsMap(subgraphsMap);\n }\n\n private async updateProcessorsForPackage(pkg: string): Promise<void> {\n this.logger.debug(`Updating processors for package: ${pkg}`);\n const processors = await this.loadProcessors([pkg]);\n const processorsMap = new Map(this.processorMap);\n const pkgProcessors = processors.get(pkg) ?? [];\n if (pkgProcessors.length === 0) {\n processorsMap.delete(pkg);\n } else {\n processorsMap.set(pkg, pkgProcessors);\n }\n this.updateProcessorsMap(processorsMap);\n }\n\n private async updatePiecesForPackage(pkg: string): Promise<void> {\n this.logger.debug(`Updating pieces for package: ${pkg}`);\n const pieces = await this.loadPieces([pkg]);\n const piecesMap = new Map(this.piecesMap);\n const pkgPieces = pieces.get(pkg) ?? [];\n if (pkgPieces.length === 0) {\n // An empty result means the package no longer contributes pieces: drop\n // the key so the change event signals removal, as its siblings do.\n piecesMap.delete(pkg);\n } else {\n piecesMap.set(pkg, pkgPieces);\n }\n this.updatePiecesMap(piecesMap);\n }\n\n /** Debounced per key so repeated subscribePackages calls reuse one timer. */\n private getDebouncedUpdateCallback(\n key: string,\n update: () => Promise<void>,\n ): () => void {\n if (!this.debouncedUpdateCallbacks.has(key)) {\n const debouncedFn = debounce(update, 1000);\n this.debouncedUpdateCallbacks.set(key, () => {\n debouncedFn().catch((error: unknown) => {\n this.logger.error(\"Failed to update package: @error\", error);\n });\n });\n }\n return this.debouncedUpdateCallbacks.get(key)!;\n }\n\n private subscribePackages(packages: string[]) {\n const unsubs: (() => void)[] = [];\n for (const pkg of packages) {\n const onDocumentModels = this.getDebouncedUpdateCallback(\n `${pkg}:document-models`,\n () => this.updateDocumentModelsForPackage(pkg),\n );\n const onSubgraphs = this.getDebouncedUpdateCallback(\n `${pkg}:subgraphs`,\n () => this.updateSubgraphsForPackage(pkg),\n );\n const onProcessors = this.getDebouncedUpdateCallback(\n `${pkg}:processors`,\n () => this.updateProcessorsForPackage(pkg),\n );\n const onPieces = this.getDebouncedUpdateCallback(`${pkg}:pieces`, () =>\n this.updatePiecesForPackage(pkg),\n );\n\n for (const loader of this.loaders) {\n if (loader.onDocumentModelsChange) {\n unsubs.push(loader.onDocumentModelsChange(pkg, onDocumentModels));\n }\n if (loader.onSubgraphsChange) {\n unsubs.push(loader.onSubgraphsChange(pkg, onSubgraphs));\n }\n if (loader.onProcessorsChange) {\n unsubs.push(loader.onProcessorsChange(pkg, onProcessors));\n }\n if (loader.onPiecesChange) {\n unsubs.push(loader.onPiecesChange(pkg, onPieces));\n }\n }\n }\n\n return () => {\n for (const unsub of unsubs) {\n unsub();\n }\n };\n }\n\n private getAllPackageNames(): string[] {\n const packageNames = this.options.packages ?? [];\n if (this.options.configFile) {\n packageNames.push(\n ...this.getPackageNamesFromConfigFile(this.options.configFile),\n );\n }\n return packageNames;\n }\n\n private getPackageNamesFromConfigFile(configFile: string) {\n const loadedConfig = getConfig(configFile);\n return loadedConfig.packages?.map((pkg) => pkg.packageName) ?? [];\n }\n\n private initConfigFileWatcher(configFile: string) {\n if (!this.configWatcher) {\n this.configWatcher = watchFile(\n configFile,\n { interval: 100 },\n (curr, prev) => {\n if (curr.mtime === prev.mtime) {\n return;\n }\n\n void this.loadPackages(this.getAllPackageNames());\n },\n );\n }\n }\n\n private updatePackagesMap(packagesMap: Map<string, DocumentModelModule[]>) {\n const oldPackages = Array.from(this.docModelsMap.keys());\n const newPackages = Array.from(packagesMap.keys());\n oldPackages\n .filter((pkg) => !newPackages.includes(pkg))\n .forEach((pkg) => {\n this.logger.info(`Removed package: ${pkg}`);\n });\n this.docModelsMap = packagesMap;\n this.eventEmitter.emit(\n \"documentModelsChange\",\n Object.fromEntries(packagesMap),\n );\n }\n\n private updateSubgraphsMap(subgraphsMap: Map<string, SubgraphClass[]>) {\n const oldPackages = Array.from(this.subgraphsMap.keys());\n const newPackages = Array.from(subgraphsMap.keys());\n oldPackages\n .filter((pkg) => !newPackages.includes(pkg))\n .forEach((pkg) => {\n this.logger.info(`Removed Subgraphs from: ${pkg}`);\n });\n this.subgraphsMap = subgraphsMap;\n this.eventEmitter.emit(\"subgraphsChange\", subgraphsMap);\n }\n\n private updateProcessorsMap(processorsMap: Map<string, Processor>) {\n const oldPackages = Array.from(this.processorMap.keys());\n const newPackages = Array.from(processorsMap.keys());\n oldPackages\n .filter((pkg) => !newPackages.includes(pkg))\n .forEach((pkg) => {\n this.logger.info(`Removed Processor Factories from: ${pkg}`);\n });\n\n this.processorMap = processorsMap;\n this.eventEmitter.emit(\"processorsChange\", processorsMap);\n }\n\n private updatePiecesMap(piecesMap: Map<string, PackagePieceEntry[]>) {\n const oldPackages = Array.from(this.piecesMap.keys());\n const newPackages = Array.from(piecesMap.keys());\n oldPackages\n .filter((pkg) => !newPackages.includes(pkg))\n .forEach((pkg) => {\n this.logger.info(\"Removed pieces from: @pkg\", pkg);\n });\n\n this.piecesMap = piecesMap;\n this.eventEmitter.emit(\"piecesChange\", piecesMap);\n }\n\n /** The pieces every loaded package ships, keyed by the package. */\n getPieces(): Map<string, PackagePieceEntry[]> {\n return new Map(this.piecesMap);\n }\n\n /**\n * Remove `pkg` from all package maps and emit the change events, tearing\n * down everything the package registered (subgraphs, processors, document\n * models). For an uninstalled package no loader can serve it again, so\n * nothing can re-add it.\n */\n removePackage(pkg: string): void {\n this.logger.info(`Removing package: ${pkg}`);\n const dropKey = <T>(map: Map<string, T>): Map<string, T> => {\n if (!map.has(pkg)) return map;\n const next = new Map(map);\n next.delete(pkg);\n return next;\n };\n\n this.docModelsMap = dropKey(this.docModelsMap);\n this.upgradeManifestsMap = dropKey(this.upgradeManifestsMap);\n this.subgraphsMap = dropKey(this.subgraphsMap);\n this.processorMap = dropKey(this.processorMap);\n this.piecesMap = dropKey(this.piecesMap);\n\n this.updatePackagesMap(this.docModelsMap);\n this.updateSubgraphsMap(this.subgraphsMap);\n this.updateProcessorsMap(this.processorMap);\n this.updatePiecesMap(this.piecesMap);\n }\n\n onDocumentModelsChange(\n handler: (documentModels: Record<string, DocumentModelModule[]>) => void,\n ): void {\n this.eventEmitter.on(\"documentModelsChange\", handler);\n }\n\n onSubgraphsChange(\n handler: (subgraphs: Map<string, SubgraphClass[]>) => void,\n ): void {\n this.eventEmitter.on(\"subgraphsChange\", handler);\n }\n\n onProcessorsChange(\n handler: (processors: Map<string, Processor>) => void,\n ): void {\n this.eventEmitter.on(\"processorsChange\", handler);\n }\n\n onPiecesChange(\n handler: (pieces: Map<string, PackagePieceEntry[]>) => void,\n ): void {\n this.eventEmitter.on(\"piecesChange\", handler);\n }\n}\n","import { AnalyticsSubgraph } from \"./graphql/analytics-subgraph.js\";\nimport { SystemSubgraph } from \"./graphql/system/subgraph.js\";\n\nexport const config = {\n basePath: process.env.BASE_PATH || \"/\",\n};\n\nexport const DefaultCoreSubgraphs = [\n AnalyticsSubgraph,\n SystemSubgraph,\n] as const;\n","import {\n createS3AttachmentBackend,\n parseAttachmentStorageConfig,\n type AttachmentDatabase,\n type IAttachmentBackend,\n type S3AttachmentBackendDependencies,\n} from \"@powerhousedao/reactor-attachments\";\nimport type { Kysely } from \"kysely\";\n\nexport type StartupAttachmentBackendOptions = {\n db: Kysely<AttachmentDatabase>;\n env?: Readonly<Record<string, string | undefined>>;\n s3Dependencies?: S3AttachmentBackendDependencies;\n};\n\n/** Filesystem is the default; explicit S3 is readiness-gated without fallback. */\nexport async function createStartupAttachmentBackend({\n db,\n env = process.env,\n s3Dependencies,\n}: StartupAttachmentBackendOptions): Promise<IAttachmentBackend | undefined> {\n const storage = parseAttachmentStorageConfig(env);\n if (storage.kind === \"filesystem\") return undefined;\n\n const backend = createS3AttachmentBackend(\n db.withSchema(\"attachments\"),\n storage.s3,\n s3Dependencies,\n );\n const health = await backend.health();\n if (!health.ready) {\n throw new Error(\"S3 attachment backend readiness check failed\");\n }\n return backend;\n}\n","import type {\n AttachmentHash,\n AttachmentRef,\n IReactorClient,\n} from \"@powerhousedao/reactor\";\nimport { createRef, parseRef } from \"@powerhousedao/reactor-attachments\";\nimport type { IAttachmentReferenceReader } from \"@powerhousedao/reactor-attachments\";\nimport type {\n CanonicalDocumentId,\n IAuthorizationService,\n} from \"./authorization.service.js\";\nimport type { CanonicalDocumentIdResolver } from \"./canonical-document-id.js\";\n\n/**\n * Whether the active Reactor composition hosts the attachment-reference\n * projection. Reported by the client initializer: the built-in stack always\n * registers it, while a caller-provided Reactor may lack the live\n * registration capability. Consumers of reference evidence must fail closed\n * when it is unavailable.\n */\nexport type AttachmentReferenceProjectionCapability =\n | { status: \"available\" }\n | {\n status: \"unavailable\";\n reason:\n | \"live-read-model-registration-unsupported\"\n | \"in-process-reactor-module-unavailable\"\n | \"initializer-did-not-report\";\n };\n\n/**\n * Outcome of an attachment read authorization. `denied` intentionally covers\n * both an unreadable document and an absent document/ref relationship so the\n * route layer cannot leak which check failed. `projection-unavailable` means\n * the reference index is not being maintained in this composition; it is\n * returned before any document-authorization or reference lookup runs.\n */\nexport type AttachmentAccessResult =\n | { kind: \"allowed\"; documentId: CanonicalDocumentId; ref: AttachmentRef }\n | { kind: \"denied\" }\n | { kind: \"projection-unavailable\" };\n\nexport interface AttachmentAccessRequest {\n documentId: string;\n attachmentRef: string;\n userAddress?: string;\n /**\n * The `did:key` of the app instance whose token authenticated the caller.\n * A policy subject is an address AND a key — a grant can name either, and a\n * document's creator is recorded by key — so a decision made from the address\n * alone answers a narrower question than the one being asked.\n */\n appKey?: string;\n}\n\n/** The reactor's read gate, as the attachment facade consults it. */\nexport type AttachmentReadGate = Pick<IReactorClient, \"isServed\" | \"get\">;\n\n/**\n * Which scopes of a document a subject may read, asked by document id.\n *\n * Structural on purpose: the composition that has a policy model to enforce\n * supplies `SyncScopeGate`, and one that does not supplies nothing at all.\n */\nexport interface IDocumentScopeGate {\n scopePredicateById(\n documentId: string,\n subject: { address?: string; key?: string },\n branch: string,\n signal?: AbortSignal,\n ): Promise<(scope: string) => boolean>;\n}\n\n/** The scope an attachment's bytes belong to: the document's own domain state. */\nconst ATTACHMENT_SCOPE = \"global\";\n\n/** The branch an attachment reference is resolved against. */\nconst ATTACHMENT_BRANCH = \"main\";\n\nexport interface IAttachmentAccessService {\n canReadAttachment(\n request: AttachmentAccessRequest,\n ): Promise<AttachmentAccessResult>;\n}\n\nconst HASH_PATTERN = /^[a-f0-9]{64}$/;\n\n/**\n * Composes document authorization with the projected document/ref\n * relationship. Order is fixed: validate ref, resolve the canonical document\n * id, decide the read, check the reactor's read gate serves the document, then\n * check the reference index and that the subject may read a scope whose\n * operations reference the attachment. A denied document never reaches the\n * reference reader, and the facade never touches attachment metadata, storage\n * backends, or presigners.\n *\n * The named document decides alone: an attachment several documents reference\n * is readable through each of them on that document's own terms.\n *\n * The read is decided by the document's own policy when this composition has a\n * model to enforce it with, and by the host's permission tables when it does\n * not. That is not a preference between two equivalent answers: a host running\n * document policies keeps no rows in the permission tables, so asking them\n * about such a document returns whatever the host-wide policy says — under\n * `OPEN`, `true`, for everyone. Serving bytes on that answer hands the file to\n * anyone who learns its hash, which the document's own state may well have told\n * them. Both are kept because they are the two halves of one rule: an\n * attachment is readable by whoever may read the document that references it,\n * and each composition can only express that in its own terms.\n */\nexport class AttachmentAccessService implements IAttachmentAccessService {\n constructor(\n private readonly resolveCanonicalId: CanonicalDocumentIdResolver,\n private readonly authorization: IAuthorizationService,\n private readonly references: IAttachmentReferenceReader,\n private readonly projection: AttachmentReferenceProjectionCapability,\n private readonly readGate: AttachmentReadGate,\n /**\n * Absent below auth enforcement, where there is no policy model to\n * evaluate; the host's permission tables decide alone, exactly as before.\n */\n private readonly scopeGate?: IDocumentScopeGate,\n ) {}\n\n async canReadAttachment(\n request: AttachmentAccessRequest,\n ): Promise<AttachmentAccessResult> {\n if (this.projection.status !== \"available\") {\n return { kind: \"projection-unavailable\" };\n }\n\n const ref = normalizeAttachmentRef(request.attachmentRef);\n if (ref === null) {\n return { kind: \"denied\" };\n }\n\n let documentId: CanonicalDocumentId;\n try {\n documentId = await this.resolveCanonicalId(request.documentId);\n } catch {\n return { kind: \"denied\" };\n }\n\n if (!(await this.canReadDocument(documentId, request))) {\n return { kind: \"denied\" };\n }\n\n const subject = { address: request.userAddress, key: request.appKey };\n\n let served: boolean;\n try {\n served = await this.readGate.isServed(documentId, { subject });\n } catch {\n return { kind: \"denied\" };\n }\n if (!served) {\n return { kind: \"denied\" };\n }\n\n const scopes = await this.references.referencingScopes(documentId, ref);\n if (scopes.length === 0) {\n return { kind: \"denied\" };\n }\n\n let held: Record<string, unknown>;\n try {\n const document = await this.readGate.get(documentId, {\n subject,\n scopes,\n });\n held = document.state as Record<string, unknown>;\n } catch {\n return { kind: \"denied\" };\n }\n if (!scopes.some((scope) => scope in held)) {\n return { kind: \"denied\" };\n }\n\n return { kind: \"allowed\", documentId, ref };\n }\n\n /**\n * Whether the caller may read the state the reference lives in.\n *\n * A failure here is rethrown rather than turned into a denial. A read side\n * that is down must not read as a policy: a denial nobody can distinguish\n * from a refusal is one nobody investigates, and the route answers 500 for a\n * reason.\n */\n private async canReadDocument(\n documentId: CanonicalDocumentId,\n request: AttachmentAccessRequest,\n ): Promise<boolean> {\n if (!this.scopeGate) {\n return this.authorization.canRead(documentId, request.userAddress);\n }\n const readable = await this.scopeGate.scopePredicateById(\n documentId,\n { address: request.userAddress, key: request.appKey },\n ATTACHMENT_BRANCH,\n );\n return readable(ATTACHMENT_SCOPE);\n }\n}\n\n/**\n * Parses and canonicalizes a caller-supplied ref through the shared parser.\n * Returns null for anything that is not a v1 ref over a 64-char SHA-256 hex\n * hash; hex case is normalized so index lookups use the canonical form.\n */\nfunction normalizeAttachmentRef(value: string): AttachmentRef | null {\n let hash: string;\n let version: number;\n try {\n const parsed = parseRef(value as AttachmentRef);\n hash = parsed.hash.toLowerCase();\n version = parsed.version;\n } catch {\n return null;\n }\n if (version !== 1 || !HASH_PATTERN.test(hash)) {\n return null;\n }\n return createRef(hash as AttachmentHash, version);\n}\n","import { getAuthContext } from \"./auth-middleware.js\";\nimport type { FetchHandler } from \"./types.js\";\n\nexport type RequireAuthFetchMiddleware = (\n handler: FetchHandler,\n) => FetchHandler;\n\n/**\n * Returns a fetch middleware that rejects anonymous callers with a 401.\n *\n * This is the enforcement half of the resolve-and-don't-enforce split set up\n * by `RESOLVE_CALLER_IDENTITY`: the auth middleware must run before this\n * one — it verifies the bearer (an invalid token is still a 401 from\n * there) and records the resolved caller on the request. This middleware\n * then refuses the request when no caller was resolved, so under `OPEN`\n * (or `AUTH_ENABLED` with identity resolution) the whole generic surface —\n * document CRUD, sync, every custom subgraph — is reachable only by\n * authenticated callers, without locking out non-admins the way\n * `ADMIN_ONLY` does.\n *\n * It composes in one place in the fetch chain, so it covers every mounted\n * subgraph, the supergraph, and the SSE handler alike.\n *\n * OPTIONS is let through: a CORS preflight never carries a bearer, and\n * `AuthService.authenticateRequest` already answers it with an anonymous\n * context — refusing it would break every cross-origin client with a 401.\n *\n * Fails closed: a request that reaches this middleware without a resolved\n * context has no caller, and is rejected. The server never composes this\n * middleware without the auth middleware in the chain (see\n * `assertRequireAuthenticatedCallerAllowed` in `server.ts`).\n *\n * `exemptPaths` names the mounted paths that stay reachable anonymously — a\n * deployment whose product has a flow that runs before sign-in, such as\n * previewing an invitation from its code, needs somewhere to serve it from.\n * Each entry is a hole in the floor, so the match is deliberately the\n * narrowest one that works: the request's pathname, compared in full. A\n * prefix rule would exempt `/graphql/public-admin` along with\n * `/graphql/public`, and an exempt surface nobody can enumerate by reading\n * the configuration is not one anybody audits.\n */\nexport function createRequireAuthFetchMiddleware(\n exemptPaths: readonly string[] = [],\n): RequireAuthFetchMiddleware {\n const exempt = new Set(exemptPaths.map(normalizeExemptPath));\n return (next: FetchHandler): FetchHandler =>\n async (request: globalThis.Request): Promise<globalThis.Response> => {\n if (request.method === \"OPTIONS\") {\n return next(request);\n }\n if (\n exempt.size > 0 &&\n exempt.has(normalizeExemptPath(new URL(request.url).pathname))\n ) {\n return next(request);\n }\n if (getAuthContext(request)?.user === undefined) {\n return new globalThis.Response(\n JSON.stringify({ error: \"Authentication required\" }),\n { status: 401 },\n );\n }\n return next(request);\n };\n}\n\n/**\n * The form both sides of the comparison are reduced to: surrounding whitespace\n * gone, and one trailing slash gone, so `/graphql/public/` and\n * `/graphql/public` are the same path. A client that appends a slash is not\n * asking for a different route, and a configuration that carries one is not\n * asking for a different rule.\n *\n * Deliberately NOT normalized: case, percent-encoding, and a missing leading\n * slash. The first two would let two spellings of one path diverge from how\n * the router itself matches; the third is a configuration error, and\n * `assertRequireAuthenticatedCallerAllowed` refuses to boot on it rather than\n * leaving an exemption that silently never applies.\n */\nfunction normalizeExemptPath(path: string): string {\n const trimmed = path.trim();\n return trimmed.length > 1 && trimmed.endsWith(\"/\")\n ? trimmed.slice(0, -1)\n : trimmed;\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<unknown>): Promise<void> {\n // Create DocumentPermission table\n await sql`\n CREATE TABLE IF NOT EXISTS \"DocumentPermission\" (\n \"id\" SERIAL PRIMARY KEY,\n \"documentId\" VARCHAR(255) NOT NULL,\n \"userAddress\" VARCHAR(255) NOT NULL,\n \"permission\" VARCHAR(20) NOT NULL CHECK (\"permission\" IN ('READ', 'WRITE', 'ADMIN')),\n \"grantedBy\" VARCHAR(255) NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n \"updatedAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n UNIQUE (\"documentId\", \"userAddress\")\n )\n `.execute(db);\n\n // Create indexes for DocumentPermission\n await sql`CREATE INDEX IF NOT EXISTS \"documentpermission_documentid_index\" ON \"DocumentPermission\" (\"documentId\")`.execute(\n db,\n );\n await sql`CREATE INDEX IF NOT EXISTS \"documentpermission_useraddress_index\" ON \"DocumentPermission\" (\"userAddress\")`.execute(\n db,\n );\n\n // Create Group table\n await sql`\n CREATE TABLE IF NOT EXISTS \"Group\" (\n \"id\" SERIAL PRIMARY KEY,\n \"name\" VARCHAR(255) NOT NULL UNIQUE,\n \"description\" TEXT,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n \"updatedAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n )\n `.execute(db);\n\n // Create UserGroup table (user-group membership)\n await sql`\n CREATE TABLE IF NOT EXISTS \"UserGroup\" (\n \"userAddress\" VARCHAR(255) NOT NULL,\n \"groupId\" INTEGER NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (\"userAddress\", \"groupId\")\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"usergroup_groupid_index\" ON \"UserGroup\" (\"groupId\")`.execute(\n db,\n );\n\n // Create DocumentGroupPermission table\n await sql`\n CREATE TABLE IF NOT EXISTS \"DocumentGroupPermission\" (\n \"id\" SERIAL PRIMARY KEY,\n \"documentId\" VARCHAR(255) NOT NULL,\n \"groupId\" INTEGER NOT NULL,\n \"permission\" VARCHAR(20) NOT NULL CHECK (\"permission\" IN ('READ', 'WRITE', 'ADMIN')),\n \"grantedBy\" VARCHAR(255) NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n \"updatedAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n UNIQUE (\"documentId\", \"groupId\")\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"documentgrouppermission_documentid_index\" ON \"DocumentGroupPermission\" (\"documentId\")`.execute(\n db,\n );\n await sql`CREATE INDEX IF NOT EXISTS \"documentgrouppermission_groupid_index\" ON \"DocumentGroupPermission\" (\"groupId\")`.execute(\n db,\n );\n\n // Create OperationUserPermission table\n await sql`\n CREATE TABLE IF NOT EXISTS \"OperationUserPermission\" (\n \"id\" SERIAL PRIMARY KEY,\n \"documentId\" VARCHAR(255) NOT NULL,\n \"operationType\" VARCHAR(255) NOT NULL,\n \"userAddress\" VARCHAR(255) NOT NULL,\n \"grantedBy\" VARCHAR(255) NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n UNIQUE (\"documentId\", \"operationType\", \"userAddress\")\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"operationuserpermission_documentid_index\" ON \"OperationUserPermission\" (\"documentId\")`.execute(\n db,\n );\n await sql`CREATE INDEX IF NOT EXISTS \"operationuserpermission_useraddress_index\" ON \"OperationUserPermission\" (\"userAddress\")`.execute(\n db,\n );\n\n // Create OperationGroupPermission table\n await sql`\n CREATE TABLE IF NOT EXISTS \"OperationGroupPermission\" (\n \"id\" SERIAL PRIMARY KEY,\n \"documentId\" VARCHAR(255) NOT NULL,\n \"operationType\" VARCHAR(255) NOT NULL,\n \"groupId\" INTEGER NOT NULL,\n \"grantedBy\" VARCHAR(255) NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n UNIQUE (\"documentId\", \"operationType\", \"groupId\")\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"operationgrouppermission_documentid_index\" ON \"OperationGroupPermission\" (\"documentId\")`.execute(\n db,\n );\n await sql`CREATE INDEX IF NOT EXISTS \"operationgrouppermission_groupid_index\" ON \"OperationGroupPermission\" (\"groupId\")`.execute(\n db,\n );\n}\n\nexport async function down(db: Kysely<unknown>): Promise<void> {\n await sql`DROP TABLE IF EXISTS \"OperationGroupPermission\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"OperationUserPermission\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"DocumentGroupPermission\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"UserGroup\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"Group\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"DocumentPermission\"`.execute(db);\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<unknown>): Promise<void> {\n await sql`\n CREATE TABLE IF NOT EXISTS \"DocumentProtection\" (\n \"documentId\" VARCHAR(255) PRIMARY KEY,\n \"protected\" BOOLEAN NOT NULL DEFAULT false,\n \"ownerAddress\" VARCHAR(255),\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n \"updatedAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"documentprotection_owneraddress_index\" ON \"DocumentProtection\" (\"ownerAddress\")`.execute(\n db,\n );\n await sql`CREATE INDEX IF NOT EXISTS \"documentprotection_protected_index\" ON \"DocumentProtection\" (\"protected\")`.execute(\n db,\n );\n}\n\nexport async function down(db: Kysely<unknown>): Promise<void> {\n await sql`DROP TABLE IF EXISTS \"DocumentProtection\"`.execute(db);\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\n/**\n * Removes the group-permission feature: the Group, UserGroup,\n * DocumentGroupPermission, and OperationGroupPermission tables. The feature had\n * no consumers and disclosed ACL/membership metadata (AUTH_REVIEW S-H3/S-H5);\n * it is retired in favor of direct user grants, ownership, and protection.\n *\n * Tables are dropped in reverse dependency order. There are no DB-enforced\n * foreign keys, so the drops cannot violate referential integrity and do not\n * touch the surviving DocumentPermission / OperationUserPermission /\n * DocumentProtection tables.\n */\nexport async function up(db: Kysely<unknown>): Promise<void> {\n await sql`DROP TABLE IF EXISTS \"OperationGroupPermission\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"DocumentGroupPermission\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"UserGroup\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"Group\"`.execute(db);\n}\n\nexport async function down(db: Kysely<unknown>): Promise<void> {\n // Recreate the group tables exactly as migration 001 created them.\n await sql`\n CREATE TABLE IF NOT EXISTS \"Group\" (\n \"id\" SERIAL PRIMARY KEY,\n \"name\" VARCHAR(255) NOT NULL UNIQUE,\n \"description\" TEXT,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n \"updatedAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n )\n `.execute(db);\n\n await sql`\n CREATE TABLE IF NOT EXISTS \"UserGroup\" (\n \"userAddress\" VARCHAR(255) NOT NULL,\n \"groupId\" INTEGER NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (\"userAddress\", \"groupId\")\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"usergroup_groupid_index\" ON \"UserGroup\" (\"groupId\")`.execute(\n db,\n );\n\n await sql`\n CREATE TABLE IF NOT EXISTS \"DocumentGroupPermission\" (\n \"id\" SERIAL PRIMARY KEY,\n \"documentId\" VARCHAR(255) NOT NULL,\n \"groupId\" INTEGER NOT NULL,\n \"permission\" VARCHAR(20) NOT NULL CHECK (\"permission\" IN ('READ', 'WRITE', 'ADMIN')),\n \"grantedBy\" VARCHAR(255) NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n \"updatedAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n UNIQUE (\"documentId\", \"groupId\")\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"documentgrouppermission_documentid_index\" ON \"DocumentGroupPermission\" (\"documentId\")`.execute(\n db,\n );\n await sql`CREATE INDEX IF NOT EXISTS \"documentgrouppermission_groupid_index\" ON \"DocumentGroupPermission\" (\"groupId\")`.execute(\n db,\n );\n\n await sql`\n CREATE TABLE IF NOT EXISTS \"OperationGroupPermission\" (\n \"id\" SERIAL PRIMARY KEY,\n \"documentId\" VARCHAR(255) NOT NULL,\n \"operationType\" VARCHAR(255) NOT NULL,\n \"groupId\" INTEGER NOT NULL,\n \"grantedBy\" VARCHAR(255) NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n UNIQUE (\"documentId\", \"operationType\", \"groupId\")\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"operationgrouppermission_documentid_index\" ON \"OperationGroupPermission\" (\"documentId\")`.execute(\n db,\n );\n await sql`CREATE INDEX IF NOT EXISTS \"operationgrouppermission_groupid_index\" ON \"OperationGroupPermission\" (\"groupId\")`.execute(\n db,\n );\n}\n","import {\n Migrator,\n type Kysely,\n type Migration,\n type MigrationProvider,\n} from \"kysely\";\nimport * as migration001 from \"./001_create_document_permissions.js\";\nimport * as migration002 from \"./002_add_document_protection.js\";\nimport * as migration003 from \"./003_remove_group_tables.js\";\n\n/**\n * Custom migration provider that loads migrations from imported modules\n */\nclass StaticMigrationProvider implements MigrationProvider {\n getMigrations(): Promise<Record<string, Migration>> {\n return Promise.resolve({\n \"001_create_document_permissions\": migration001,\n \"002_add_document_protection\": migration002,\n \"003_remove_group_tables\": migration003,\n });\n }\n}\n\n/**\n * Run all pending migrations\n */\nexport async function runMigrations(db: Kysely<unknown>): Promise<void> {\n const migrator = new Migrator({\n db,\n provider: new StaticMigrationProvider(),\n });\n\n const { error, results } = await migrator.migrateToLatest();\n\n results?.forEach((result) => {\n if (result.status === \"Error\") {\n console.error(`Failed to execute migration \"${result.migrationName}\"`);\n }\n });\n\n if (error) {\n console.error(\"Failed to run migrations:\", error);\n const errorMessage =\n error instanceof Error ? error.message : \"Unknown error\";\n throw new Error(`Migration failed: ${errorMessage}`);\n }\n}\n\n/**\n * Rollback the last migration\n */\nexport async function rollbackMigration(db: Kysely<unknown>): Promise<void> {\n const migrator = new Migrator({\n db,\n provider: new StaticMigrationProvider(),\n });\n\n const { error, results } = await migrator.migrateDown();\n\n results?.forEach((result) => {\n if (result.status === \"Success\") {\n console.log(\n `Migration \"${result.migrationName}\" was rolled back successfully`,\n );\n } else if (result.status === \"Error\") {\n console.error(`Failed to rollback migration \"${result.migrationName}\"`);\n }\n });\n\n if (error) {\n console.error(\"Failed to rollback migration:\", error);\n const errorMessage =\n error instanceof Error ? error.message : \"Unknown error\";\n throw new Error(`Rollback failed: ${errorMessage}`);\n }\n}\n","import type { RouteUser } from \"@powerhousedao/shared/processors\";\nimport { verifyAuthBearerToken } from \"@renown/sdk\";\n\ntype VerifiedCredential =\n Awaited<ReturnType<typeof verifyAuthBearerToken>> extends false | (infer T)\n ? T\n : never;\n\n// Confirms an authenticated signer's credential is still valid. Injected so\n// AuthService stays agnostic to how/where credentials are verified.\nexport type CredentialVerifier = (params: {\n address: string;\n chainId: number;\n appId: string;\n}) => Promise<boolean>;\n\nexport interface AuthConfig {\n /**\n * Whether the authorization policy enforces anything: it selects `ADMIN_ONLY`\n * over `OPEN`, and it is what `AuthContext.auth_enabled` reports to callers\n * that gate on \"is authentication being enforced\" (the attachment routes do).\n *\n * It does NOT decide whether the bearer is read — see {@link resolveIdentity}.\n */\n enabled: boolean;\n /**\n * Whether the bearer is verified and `AuthContext.user` populated at all.\n *\n * Defaults to {@link enabled}, which is the behaviour every deployment had\n * before this option existed. Setting it independently is what lets a server\n * know who is calling while leaving the policy `OPEN` — resolving an identity\n * and enforcing one are different concerns, and welding them together left\n * consumers choosing between an unauthenticated caller and locking every\n * non-admin out.\n *\n * It resolves an identity and enforces nothing: a request with no token is\n * still admitted, with no user.\n */\n resolveIdentity?: boolean;\n admins: string[];\n skipCredentialVerification?: boolean; // DANGER: removes identity verification; boot-gated to test/dev\n credentialVerificationCacheTtlMs?: number; // How long successful Renown credential checks are cached; 0 disables caching\n verifyCredential?: CredentialVerifier; // Injected credential check; required when verification is on\n}\n\nconst DEFAULT_CREDENTIAL_CACHE_TTL_MS = 60_000;\nconst CREDENTIAL_CACHE_MAX_ENTRIES = 1_000;\n\ninterface CredentialCacheEntry {\n exists: Promise<boolean>;\n expiresAt: number;\n}\n\n/**\n * The authenticated principal. The shape is declared once in\n * `@powerhousedao/shared/processors` as `RouteUser`, so a route handler and a\n * resolver agree on it without either package redeclaring it.\n */\nexport type User = RouteUser;\n\nexport interface AuthContext {\n user?: User;\n admins: string[];\n auth_enabled: boolean;\n}\n\nexport class AuthService {\n private readonly config: AuthConfig;\n private readonly credentialCache = new Map<string, CredentialCacheEntry>();\n\n constructor(config: AuthConfig) {\n this.config = config;\n }\n\n /**\n * Whether this service reads the bearer at all. Defaults to `enabled`, so a\n * config written before `resolveIdentity` existed behaves exactly as it did.\n */\n private get resolvesIdentity(): boolean {\n return this.config.resolveIdentity ?? this.config.enabled;\n }\n\n /** The context an unresolved request gets: no user, and no admin list to match against. */\n private anonymousContext(): AuthContext {\n return { user: undefined, admins: [], auth_enabled: this.config.enabled };\n }\n\n async authenticateRequest(\n request: globalThis.Request,\n ): Promise<AuthContext | globalThis.Response> {\n if (!this.resolvesIdentity) {\n return this.anonymousContext();\n }\n // OPTIONS is a CORS preflight: it never carries application auth. Every\n // other method verifies whatever token it carries -- a GET query's payload\n // can be an authorization verdict, so discarding its token would silently\n // answer for the anonymous subject instead of the authenticated caller.\n // A GET without a token stays anonymous, as verifyBearer already allows.\n if (request.method === \"OPTIONS\") {\n return {\n user: undefined,\n admins: this.config.admins,\n auth_enabled: this.config.enabled,\n };\n }\n return this.verifyBearer(request.headers.get(\"authorization\") ?? undefined);\n }\n\n /**\n * Verify a Bearer token regardless of HTTP method. Use this from non-GraphQL\n * middleware that must enforce authentication on every request.\n */\n async verifyBearer(\n authorization: string | undefined,\n ): Promise<AuthContext | globalThis.Response> {\n if (!this.resolvesIdentity) {\n return this.anonymousContext();\n }\n const token = authorization?.split(\" \")[1];\n if (!token) {\n return {\n user: undefined,\n admins: this.config.admins,\n auth_enabled: this.config.enabled,\n };\n }\n try {\n const verified = await this.verifyToken(token);\n if (!verified) {\n return new Response(JSON.stringify({ error: \"Verification failed\" }), {\n status: 401,\n });\n }\n const user = this.extractUserFromVerification(verified);\n if (!user) {\n return new Response(JSON.stringify({ error: \"Missing credentials\" }), {\n status: 401,\n });\n }\n if (!this.config.skipCredentialVerification) {\n const credentialExists = await this.verifyCredentialExists(\n user.address,\n user.chainId,\n verified.issuer,\n );\n if (!credentialExists) {\n return new Response(\n JSON.stringify({ error: \"Credentials no longer valid\" }),\n { status: 401 },\n );\n }\n }\n return {\n user,\n admins: this.config.admins,\n auth_enabled: this.config.enabled,\n };\n } catch {\n return new Response(JSON.stringify({ error: \"Authentication failed\" }), {\n status: 401,\n });\n }\n }\n\n // `null` when there is nobody to resolve: resolution off, or no bearer sent.\n\n /** Throws only for a bearer that is present and unusable, as HTTP 401s it. */\n async authenticateWebSocketConnection(\n connectionParams: Record<string, unknown>,\n ): Promise<User | null> {\n if (!this.resolvesIdentity) {\n return null;\n }\n\n const authHeader = connectionParams.authorization as string | undefined;\n if (!authHeader) {\n // Resolution, not enforcement: `verifyBearer` answers the same.\n\n // Refusing anonymous is onConnect's, keyed on REQUIRE_AUTHENTICATED_CALLER.\n\n // Subscriptions themselves authorize per document.\n return null;\n }\n\n const token = authHeader.split(\" \")[1];\n if (!token) {\n throw new Error(\"Invalid authorization format\");\n }\n\n const verified = await this.verifyToken(token);\n if (!verified) {\n throw new Error(\"Token verification failed\");\n }\n\n const user = this.extractUserFromVerification(verified);\n if (!user) {\n throw new Error(\"Invalid credentials\");\n }\n\n if (!this.config.skipCredentialVerification) {\n const credentialExists = await this.verifyCredentialExists(\n user.address,\n user.chainId,\n verified.issuer,\n );\n if (!credentialExists) {\n throw new Error(\"Credentials no longer valid\");\n }\n }\n\n // Note: We no longer block based on global allowed lists.\n // Authorization is handled at the resolver level based on document permissions.\n\n return user;\n }\n\n /**\n * Verify the auth bearer token\n */\n private async verifyToken(token: string) {\n return await verifyAuthBearerToken(token);\n }\n\n /**\n * Extract user information from verification result.\n *\n * The issuer is required along with the credential subject. A credential that\n * verified must carry one -- resolving it is how the signature was checked --\n * so this rejects a shape that cannot have come from verification rather than\n * admitting a keyless principal.\n */\n private extractUserFromVerification(\n verified: VerifiedCredential,\n ): User | null {\n try {\n const { address, chainId, networkId } =\n verified.verifiableCredential.credentialSubject;\n const appKey = verified.issuer;\n\n if (!address || !chainId || !networkId || !appKey) {\n return null;\n }\n\n return {\n address,\n chainId,\n networkId,\n appKey,\n };\n } catch {\n return null;\n }\n }\n\n /**\n * Verify that the credential still exists on the Renown API.\n *\n * Results are cached per (address, chainId, issuer) for a short TTL so the\n * blocking external round-trip is not paid on every request. Concurrent\n * checks for the same key share a single in-flight request, and entries\n * that resolve to false are evicted immediately so failed or revoked\n * credentials are re-checked on the next request.\n */\n private verifyCredentialExists(\n address: string,\n chainId: number,\n appId: string,\n ): Promise<boolean> {\n const ttlMs =\n this.config.credentialVerificationCacheTtlMs ??\n DEFAULT_CREDENTIAL_CACHE_TTL_MS;\n if (ttlMs <= 0) {\n return this.fetchCredentialExists(address, chainId, appId);\n }\n\n const key = `${address.toLowerCase()}:${chainId}:${appId}`;\n const now = Date.now();\n const cached = this.credentialCache.get(key);\n if (cached && cached.expiresAt > now) {\n return cached.exists;\n }\n\n this.pruneCredentialCache(now);\n const entry: CredentialCacheEntry = {\n exists: this.fetchCredentialExists(address, chainId, appId).then(\n (exists) => {\n if (!exists && this.credentialCache.get(key) === entry) {\n this.credentialCache.delete(key);\n }\n return exists;\n },\n ),\n expiresAt: now + ttlMs,\n };\n this.credentialCache.set(key, entry);\n return entry.exists;\n }\n\n /**\n * Enforce the cache size cap before inserting a new entry: drop expired\n * entries first, then evict oldest-inserted entries (insertion order\n * matches expiry order since the TTL is constant) until under the cap, so\n * a flood of distinct keys cannot grow the map without bound.\n */\n private pruneCredentialCache(now: number): void {\n if (this.credentialCache.size < CREDENTIAL_CACHE_MAX_ENTRIES) {\n return;\n }\n for (const [key, entry] of this.credentialCache) {\n if (entry.expiresAt <= now) {\n this.credentialCache.delete(key);\n }\n }\n while (this.credentialCache.size >= CREDENTIAL_CACHE_MAX_ENTRIES) {\n const oldestKey = this.credentialCache.keys().next().value;\n if (oldestKey === undefined) {\n break;\n }\n this.credentialCache.delete(oldestKey);\n }\n }\n\n // Confirm the signer's credential is still valid via the injected verifier.\n // Reached only when verification is on, so a missing verifier is misconfig.\n private async fetchCredentialExists(\n address: string,\n chainId: number,\n appId: string,\n ): Promise<boolean> {\n if (!this.config.verifyCredential) {\n throw new Error(\n \"AuthService: credential verification is enabled but no verifyCredential was provided\",\n );\n }\n return this.config.verifyCredential({ address, chainId, appId });\n }\n}\n","import {\n fetchDelegationCredential,\n resolveSwitchboardEndpoint,\n} from \"@renown/sdk\";\nimport type { CredentialVerifier } from \"./auth.service.js\";\n\nexport interface RenownCredentialVerifierConfig {\n // Renown base URL for the REST/discovery path. Defaults to the SDK default.\n renownUrl?: string;\n // Switchboard GraphQL endpoint; when reachable, read the reactor directly.\n switchboardUrl?: string;\n}\n\n// A CredentialVerifier backed by Renown. Resolves the switchboard endpoint once\n// at creation so each verify call skips discovery; falls back to REST otherwise.\nexport async function createRenownCredentialVerifier(\n config: RenownCredentialVerifierConfig = {},\n): Promise<CredentialVerifier> {\n const switchboardUrl = await resolveSwitchboardEndpoint({\n switchboardUrl: config.switchboardUrl,\n baseUrl: config.renownUrl,\n });\n\n return async ({ address, chainId, appId }) => {\n const credential = await fetchDelegationCredential({\n address,\n chainId,\n appDid: appId,\n // Endpoint resolved once at creation: use it, or REST — never re-discover.\n switchboardUrl,\n baseUrl: switchboardUrl ? undefined : config.renownUrl,\n discover: false,\n });\n return credential !== undefined;\n };\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\nimport type {\n DocumentPermissionDatabase,\n DocumentPermissionLevel,\n} from \"../utils/db.js\";\n\nexport interface DocumentPermissionEntry {\n documentId: string;\n userAddress: string;\n permission: DocumentPermissionLevel;\n grantedBy: string;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface OperationUserPermissionEntry {\n documentId: string;\n operationType: string;\n userAddress: string;\n grantedBy: string;\n createdAt: Date;\n}\n\n/**\n * Function type for getting parent document IDs\n * This is injected to avoid circular dependencies with the reactor client\n */\nexport type GetParentIdsFn = (documentId: string) => Promise<string[]>;\n\n/**\n * Configuration for the DocumentPermissionService\n */\nexport interface DocumentPermissionConfig {\n defaultProtection: boolean;\n}\n\n/**\n * Service for managing document-level permissions.\n *\n * Permission levels for documents:\n * - READ: Can fetch and read the document\n * - WRITE: Can push updates and modify the document\n * - ADMIN: Can manage document permissions and settings\n *\n * Operation permissions:\n * - Users can be granted permission to execute specific operations\n */\nexport class DocumentPermissionService {\n readonly config: DocumentPermissionConfig;\n\n constructor(\n private readonly db: Kysely<DocumentPermissionDatabase>,\n config: DocumentPermissionConfig = { defaultProtection: false },\n ) {\n this.config = config;\n }\n\n // ============================================\n // User Permission Operations\n // ============================================\n\n /**\n * Get the permission level for a user on a specific document.\n * Returns null if no permission is set.\n */\n async getUserPermission(\n documentId: string,\n userAddress: string,\n ): Promise<DocumentPermissionLevel | null> {\n const result = await this.db\n .selectFrom(\"DocumentPermission\")\n .select(\"permission\")\n .where(\"documentId\", \"=\", documentId)\n .where(\"userAddress\", \"=\", userAddress.toLowerCase())\n .executeTakeFirst();\n\n return result?.permission ?? null;\n }\n\n /**\n * Get all permissions for a document\n */\n async getDocumentPermissions(\n documentId: string,\n ): Promise<DocumentPermissionEntry[]> {\n const results = await this.db\n .selectFrom(\"DocumentPermission\")\n .select([\n \"documentId\",\n \"userAddress\",\n \"permission\",\n \"grantedBy\",\n \"createdAt\",\n \"updatedAt\",\n ])\n .where(\"documentId\", \"=\", documentId)\n .execute();\n\n return results;\n }\n\n /**\n * Get all documents a user has explicit access to\n */\n async getUserDocuments(\n userAddress: string,\n ): Promise<DocumentPermissionEntry[]> {\n const results = await this.db\n .selectFrom(\"DocumentPermission\")\n .select([\n \"documentId\",\n \"userAddress\",\n \"permission\",\n \"grantedBy\",\n \"createdAt\",\n \"updatedAt\",\n ])\n .where(\"userAddress\", \"=\", userAddress.toLowerCase())\n .execute();\n\n return results;\n }\n\n /**\n * Grant or update a user's permission on a document.\n */\n async grantPermission(\n documentId: string,\n userAddress: string,\n permission: DocumentPermissionLevel,\n grantedBy: string,\n ): Promise<DocumentPermissionEntry> {\n const now = new Date();\n const normalizedAddress = userAddress.toLowerCase();\n\n await this.db\n .insertInto(\"DocumentPermission\")\n .values({\n documentId,\n userAddress: normalizedAddress,\n permission,\n grantedBy: grantedBy.toLowerCase(),\n createdAt: now,\n updatedAt: now,\n })\n .onConflict((oc) =>\n oc.columns([\"documentId\", \"userAddress\"]).doUpdateSet({\n permission,\n grantedBy: grantedBy.toLowerCase(),\n updatedAt: now,\n }),\n )\n .execute();\n\n const result = await this.db\n .selectFrom(\"DocumentPermission\")\n .select([\n \"documentId\",\n \"userAddress\",\n \"permission\",\n \"grantedBy\",\n \"createdAt\",\n \"updatedAt\",\n ])\n .where(\"documentId\", \"=\", documentId)\n .where(\"userAddress\", \"=\", normalizedAddress)\n .executeTakeFirstOrThrow();\n\n return result;\n }\n\n /**\n * Revoke a user's permission on a document\n */\n async revokePermission(\n documentId: string,\n userAddress: string,\n ): Promise<void> {\n await this.db\n .deleteFrom(\"DocumentPermission\")\n .where(\"documentId\", \"=\", documentId)\n .where(\"userAddress\", \"=\", userAddress.toLowerCase())\n .execute();\n }\n\n /**\n * Delete all permissions for a document (used when deleting a document)\n */\n async deleteAllDocumentPermissions(documentId: string): Promise<void> {\n await this.db\n .deleteFrom(\"DocumentPermission\")\n .where(\"documentId\", \"=\", documentId)\n .execute();\n\n await this.db\n .deleteFrom(\"OperationUserPermission\")\n .where(\"documentId\", \"=\", documentId)\n .execute();\n }\n\n // ============================================\n // Operation Permissions\n // ============================================\n\n /**\n * Grant a user permission to execute an operation on a document\n */\n async grantOperationPermission(\n documentId: string,\n operationType: string,\n userAddress: string,\n grantedBy: string,\n ): Promise<OperationUserPermissionEntry> {\n const now = new Date();\n const normalizedAddress = userAddress.toLowerCase();\n\n await this.db\n .insertInto(\"OperationUserPermission\")\n .values({\n documentId,\n operationType,\n userAddress: normalizedAddress,\n grantedBy: grantedBy.toLowerCase(),\n createdAt: now,\n })\n .onConflict((oc) =>\n oc.columns([\"documentId\", \"operationType\", \"userAddress\"]).doNothing(),\n )\n .execute();\n\n const result = await this.db\n .selectFrom(\"OperationUserPermission\")\n .select([\n \"documentId\",\n \"operationType\",\n \"userAddress\",\n \"grantedBy\",\n \"createdAt\",\n ])\n .where(\"documentId\", \"=\", documentId)\n .where(\"operationType\", \"=\", operationType)\n .where(\"userAddress\", \"=\", normalizedAddress)\n .executeTakeFirstOrThrow();\n\n return result;\n }\n\n /**\n * Revoke a user's permission to execute an operation\n */\n async revokeOperationPermission(\n documentId: string,\n operationType: string,\n userAddress: string,\n ): Promise<void> {\n await this.db\n .deleteFrom(\"OperationUserPermission\")\n .where(\"documentId\", \"=\", documentId)\n .where(\"operationType\", \"=\", operationType)\n .where(\"userAddress\", \"=\", userAddress.toLowerCase())\n .execute();\n }\n\n /**\n * Get all users with permission to execute an operation\n */\n async getOperationUserPermissions(\n documentId: string,\n operationType: string,\n ): Promise<OperationUserPermissionEntry[]> {\n return this.db\n .selectFrom(\"OperationUserPermission\")\n .select([\n \"documentId\",\n \"operationType\",\n \"userAddress\",\n \"grantedBy\",\n \"createdAt\",\n ])\n .where(\"documentId\", \"=\", documentId)\n .where(\"operationType\", \"=\", operationType)\n .execute();\n }\n\n /**\n * Whether an operation-permission row exists for the user on this operation.\n */\n async hasOperationGrant(\n documentId: string,\n operationType: string,\n userAddress: string,\n ): Promise<boolean> {\n const normalizedAddress = userAddress.toLowerCase();\n\n const userPermission = await this.db\n .selectFrom(\"OperationUserPermission\")\n .select(\"userAddress\")\n .where(\"documentId\", \"=\", documentId)\n .where(\"operationType\", \"=\", operationType)\n .where(\"userAddress\", \"=\", normalizedAddress)\n .executeTakeFirst();\n\n return !!userPermission;\n }\n\n /**\n * Check if an operation has any permissions set (is restricted)\n */\n async isOperationRestricted(\n documentId: string,\n operationType: string,\n ): Promise<boolean> {\n const userPermCount = await this.db\n .selectFrom(\"OperationUserPermission\")\n .select(sql<number>`count(*)`.as(\"count\"))\n .where(\"documentId\", \"=\", documentId)\n .where(\"operationType\", \"=\", operationType)\n .executeTakeFirst();\n\n return userPermCount !== undefined && Number(userPermCount.count) > 0;\n }\n\n // ============================================\n // Document Protection\n // ============================================\n\n /**\n * Check if a specific document has a protection row set to true.\n * Falls back to `config.defaultProtection` if no row exists.\n */\n async isDocumentProtected(documentId: string): Promise<boolean> {\n const row = await this.db\n .selectFrom(\"DocumentProtection\")\n .select(\"protected\")\n .where(\"documentId\", \"=\", documentId)\n .executeTakeFirst();\n\n if (row === undefined) {\n return this.config.defaultProtection;\n }\n\n return row.protected;\n }\n\n /**\n * Walk the parent chain: if the document itself or any ancestor is protected, return true.\n * Collects all ancestor IDs first (with cycle detection), then batch-checks protection.\n */\n async isProtectedWithAncestors(\n documentId: string,\n getParentIds: GetParentIdsFn,\n ): Promise<boolean> {\n // Collect all IDs in the hierarchy (document + all ancestors)\n const allIds = await this.collectAncestorIds(documentId, getParentIds);\n\n // Batch-check protection for all IDs at once\n if (allIds.length === 0) {\n return this.config.defaultProtection;\n }\n\n const rows = await this.db\n .selectFrom(\"DocumentProtection\")\n .select([\"documentId\", \"protected\"])\n .where(\"documentId\", \"in\", allIds)\n .execute();\n\n const protectionMap = new Map(rows.map((r) => [r.documentId, r.protected]));\n\n for (const id of allIds) {\n const isProtected = protectionMap.get(id);\n // If no row exists, fall back to defaultProtection\n if (isProtected ?? this.config.defaultProtection) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Collect all ancestor IDs (including the document itself) with cycle detection.\n */\n private async collectAncestorIds(\n documentId: string,\n getParentIds: GetParentIdsFn,\n ): Promise<string[]> {\n const visited = new Set<string>();\n const queue = [documentId];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n if (visited.has(current)) continue;\n visited.add(current);\n\n const parentIds = await getParentIds(current);\n for (const parentId of parentIds) {\n if (!visited.has(parentId)) {\n queue.push(parentId);\n }\n }\n }\n\n return Array.from(visited);\n }\n\n /**\n * Upsert protection status for a document.\n */\n async setDocumentProtection(\n documentId: string,\n isProtected: boolean,\n ): Promise<void> {\n const now = new Date();\n\n await this.db\n .insertInto(\"DocumentProtection\")\n .values({\n documentId,\n protected: isProtected,\n ownerAddress: null,\n createdAt: now,\n updatedAt: now,\n })\n .onConflict((oc) =>\n oc.column(\"documentId\").doUpdateSet({\n protected: isProtected,\n updatedAt: now,\n }),\n )\n .execute();\n }\n\n /**\n * Get the owner address for a document, or null if not set.\n */\n async getDocumentOwner(documentId: string): Promise<string | null> {\n const row = await this.db\n .selectFrom(\"DocumentProtection\")\n .select(\"ownerAddress\")\n .where(\"documentId\", \"=\", documentId)\n .executeTakeFirst();\n\n return row?.ownerAddress ?? null;\n }\n\n /**\n * Upsert owner address for a document.\n */\n async setDocumentOwner(\n documentId: string,\n ownerAddress: string,\n ): Promise<void> {\n const now = new Date();\n const normalizedAddress = ownerAddress.toLowerCase();\n\n await this.db\n .insertInto(\"DocumentProtection\")\n .values({\n documentId,\n protected: this.config.defaultProtection,\n ownerAddress: normalizedAddress,\n createdAt: now,\n updatedAt: now,\n })\n .onConflict((oc) =>\n oc.column(\"documentId\").doUpdateSet({\n ownerAddress: normalizedAddress,\n updatedAt: now,\n }),\n )\n .execute();\n }\n\n /**\n * Initialize protection for a newly created document.\n * Sets protection status and grants ADMIN to the owner.\n */\n async initializeDocumentProtection(\n documentId: string,\n ownerAddress: string,\n defaultProtection?: boolean,\n ): Promise<void> {\n const now = new Date();\n const normalizedAddress = ownerAddress.toLowerCase();\n const isProtected = defaultProtection ?? this.config.defaultProtection;\n\n await this.db\n .insertInto(\"DocumentProtection\")\n .values({\n documentId,\n protected: isProtected,\n ownerAddress: normalizedAddress,\n createdAt: now,\n updatedAt: now,\n })\n .onConflict((oc) =>\n oc.column(\"documentId\").doUpdateSet({\n ownerAddress: normalizedAddress,\n updatedAt: now,\n }),\n )\n .execute();\n\n // Grant ADMIN permission to the owner\n await this.grantPermission(\n documentId,\n normalizedAddress,\n \"ADMIN\",\n normalizedAddress,\n );\n }\n\n /**\n * Get the full protection info for a document.\n */\n async getDocumentProtection(documentId: string): Promise<{\n documentId: string;\n protected: boolean;\n ownerAddress: string | null;\n }> {\n const row = await this.db\n .selectFrom(\"DocumentProtection\")\n .select([\"documentId\", \"protected\", \"ownerAddress\"])\n .where(\"documentId\", \"=\", documentId)\n .executeTakeFirst();\n\n if (!row) {\n return {\n documentId,\n protected: this.config.defaultProtection,\n ownerAddress: null,\n };\n }\n\n return row;\n }\n}\n","import type { IReactorClient } from \"@powerhousedao/reactor\";\nimport type { GetParentIdsFn } from \"./document-permission.service.js\";\n\n/**\n * The canonical parent-document resolver used for permission inheritance:\n * a document's parents are the sources of its incoming \"child\"\n * relationships. Lookup failures resolve to \"no parents\" so a relationship\n * store outage degrades to no inherited permissions rather than an error.\n */\nexport function createGetParentIdsFn(\n reactorClient: IReactorClient,\n): GetParentIdsFn {\n return async (documentId: string): Promise<string[]> => {\n try {\n const result = await reactorClient.getIncomingRelationships(\n documentId,\n \"child\",\n );\n return result.results.map((doc) => doc.header.id);\n } catch {\n return [];\n }\n };\n}\n","import type { McpRequestAuthorizer } from \"@powerhousedao/reactor-mcp\";\nimport type { AuthService } from \"./auth.service.js\";\nimport {\n AuthorizationPolicy,\n type IAuthorizationService,\n} from \"./authorization.service.js\";\n\n/**\n * Authorization gate for the /mcp endpoint (AUTH_REVIEW S-C1). MCP tools have\n * unrestricted reactor access, so access is limited to supreme admins when\n * auth is enabled. OPEN policy is public; any other policy without an\n * AuthService fails closed. The tools read as the caller: anonymous under OPEN,\n * else the admin's address and the app key its token carries.\n */\nexport function createMcpRequestAuthorizer(\n authService: AuthService | undefined,\n authorizationService: IAuthorizationService,\n): McpRequestAuthorizer {\n return async (req) => {\n if (!authService) {\n if (authorizationService.config.policy === AuthorizationPolicy.OPEN) {\n return { authorized: true, subject: {} };\n }\n return {\n authorized: false,\n status: 401,\n message: \"Authentication required\",\n };\n }\n\n const context = await authService.verifyBearer(req.headers.authorization);\n if (context instanceof Response) {\n return {\n authorized: false,\n status: context.status,\n message: \"Authentication failed\",\n };\n }\n if (!context.user) {\n return {\n authorized: false,\n status: 401,\n message: \"Authentication required\",\n };\n }\n if (!authorizationService.isSupremeAdmin(context.user.address)) {\n return {\n authorized: false,\n status: 403,\n message: \"Forbidden: MCP access requires an administrator\",\n };\n }\n return {\n authorized: true,\n subject: { address: context.user.address, key: context.user.appKey },\n };\n };\n}\n","import type { InProcessReactorModule } from \"@powerhousedao/reactor\";\nimport {\n BareReadGate,\n ModelReadGate,\n readDecisionModel,\n SyncScopeGate,\n} from \"@powerhousedao/reactor\";\nimport type { ILogger } from \"document-model\";\nimport type { AuthorizationConfig } from \"./authorization.service.js\";\n\n/**\n * The gate sync serving evaluates a document's own policy through, deciding\n * what the reactor client's read gate decides at the same flag level.\n *\n * Under `authEnforcement` it is built here rather than taken off the client\n * because it also carries the host's closes-by-default setting, which withholds\n * the domain scopes of a document nobody has policied yet. That answer belongs\n * to serving alone -- replay must keep reading an uninitialized document in\n * full -- so the two gates are separate objects over the same model.\n *\n * Below it the registered model ignores the auth scope, so the client reads\n * through the policy alone, and so does serving: a policy written below the\n * flag still withholds, where serving ungated would sync to a peer what `get`\n * refuses it.\n */\nexport function buildSyncServingGate(\n reactorModule: InProcessReactorModule | undefined,\n authorizationConfig: AuthorizationConfig,\n logger: ILogger,\n): SyncScopeGate | undefined {\n if (!reactorModule) {\n return undefined;\n }\n\n const model = readDecisionModel(\n reactorModule.featureFlags,\n reactorModule.documentModelRegistry,\n );\n if (!model) {\n return new SyncScopeGate(\n new BareReadGate(),\n reactorModule.documentView,\n logger,\n );\n }\n\n return new SyncScopeGate(\n new ModelReadGate(\n model,\n reactorModule.documentView,\n reactorModule.featureFlags.authGroups,\n reactorModule.operationIndex,\n logger,\n { withholdUninitialized: authorizationConfig.defaultProtection },\n ),\n reactorModule.documentView,\n logger,\n );\n}\n","import type { PHReactorRenown } from \"@powerhousedao/shared/clis\";\nimport type { ILogger } from \"document-model\";\n\n/** Where the credential check reads from: a remote Renown or Switchboard\n * instance, or this switchboard's own renown read model. */\nexport type RenownSource = NonNullable<PHReactorRenown[\"source\"]>;\n\n/** The `auth.renown` config block: which Renown instance to authenticate\n * against, before env overrides are applied. */\nexport type RenownConfig = PHReactorRenown;\n\n/** Resolved renown coordinates. `url` also drives this reactor's own identity,\n * so it stays meaningful when `source` is \"self\". */\nexport type ResolvedRenownConfig = {\n source: RenownSource;\n url: string | undefined;\n switchboardUrl: string | undefined;\n};\n\n/** Reading credentials from this reactor's own read model needs a host-supplied\n * verifier: core has no idea which subgraph serves that read model. */\nexport function assertCredentialVerifierForSource(\n source: RenownSource,\n hasVerifier: boolean,\n): void {\n if (source !== \"self\" || hasVerifier) {\n return;\n }\n throw new Error(\n 'Renown credential verification is set to \"self\" (auth.renown.source or ' +\n \"RENOWN_SOURCE) but no verifyCredential was provided. A host that reads \" +\n \"its own read model must pass one — see apps/switchboard, which builds \" +\n \"it from @renown/sdk createLocalCredentialVerifier — or set \" +\n \"RENOWN_SOURCE=remote to verify against a Renown instance.\",\n );\n}\n\n// Treat a blank env var as unset so `RENOWN_URL=` cannot blank out the config.\nfunction envOverride(value: string | undefined): string | undefined {\n const trimmed = value?.trim();\n return trimmed ? trimmed : undefined;\n}\n\n/** Resolve `auth.renown`; RENOWN_SOURCE / RENOWN_URL / SWITCHBOARD_URL win\n * over the config file, which wins over the SDK defaults. */\nexport function resolveRenownConfig(\n configured: RenownConfig | undefined,\n env: NodeJS.ProcessEnv,\n logger: ILogger,\n): ResolvedRenownConfig {\n return {\n source: resolveRenownSource(\n envOverride(env.RENOWN_SOURCE) ?? configured?.source,\n logger,\n ),\n url: envOverride(env.RENOWN_URL) ?? configured?.url,\n switchboardUrl:\n envOverride(env.SWITCHBOARD_URL) ?? configured?.switchboardUrl,\n };\n}\n\n// `null` is reachable despite the types: it is what `\"source\": null` in the\n// config file deserialises to, and counts as unset like a blank env var.\nfunction resolveRenownSource(\n value: string | null | undefined,\n logger: ILogger,\n): RenownSource {\n if (value === undefined || value === null) {\n return \"remote\";\n }\n if (value === \"self\" || value === \"remote\") {\n return value;\n }\n logger.warn(\n `Ignoring invalid renown source \"${value}\" (expected \"self\" or \"remote\") — using \"remote\"`,\n );\n return \"remote\";\n}\n","import { PGlite } from \"@electric-sql/pglite\";\nimport type { PGlite as PGliteType } from \"@electric-sql/pglite\";\nimport { AtomicNodeFs } from \"@powerhousedao/pglite-fs\";\nimport type { Knex } from \"knex\";\nimport knex from \"knex\";\nimport ClientPgLite from \"knex-pglite\";\nimport { type Generated, Kysely } from \"kysely\";\nimport { KyselyKnexDialect, PGColdDialect } from \"kysely-knex\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * Permission levels for documents:\n * - READ: Can fetch and read the document\n * - WRITE: Can push updates and modify the document\n * - ADMIN: Can manage document permissions and settings\n */\nexport type DocumentPermissionLevel = \"READ\" | \"WRITE\" | \"ADMIN\";\n\n/**\n * Database schema for document permissions\n */\nexport interface DocumentProtectionTable {\n documentId: string;\n protected: boolean;\n ownerAddress: string | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface DocumentPermissionDatabase {\n DocumentPermission: DocumentPermissionTable;\n OperationUserPermission: OperationUserPermissionTable;\n DocumentProtection: DocumentProtectionTable;\n}\n\nexport interface DocumentPermissionTable {\n id: Generated<number>;\n documentId: string;\n userAddress: string;\n permission: DocumentPermissionLevel;\n grantedBy: string;\n createdAt: Date;\n updatedAt: Date;\n}\n\n// Operation permission tables\nexport interface OperationUserPermissionTable {\n id: Generated<number>;\n documentId: string;\n operationType: string;\n userAddress: string;\n grantedBy: string;\n createdAt: Date;\n}\n\ntype Db = Kysely<any>;\n\n// PGlite parses `timestamp` (no tz) columns as local time; read-model columns\n// store UTC, so parse them as UTC or values shift by the host's TZ offset.\nexport const PGLITE_UTC_PARSERS = {\n // 1114 = timestamp without time zone\n 1114: (value: string) => new Date(`${value.replace(\" \", \"T\")}Z`),\n} as const;\n\nfunction isPG(connectionString: string) {\n if (\n connectionString.startsWith(\"postgresql://\") ||\n connectionString.startsWith(\"postgres://\")\n ) {\n return true;\n }\n return false;\n}\n\n/**\n * Optional factory used by callers (e.g. Switchboard) to inject a\n * version-specific PGLite instance — e.g. `pglite-legacy-02` when an existing\n * data dir was created with an older PG major. Wire-compatible with the\n * current PGLite class for the surface knex-pglite uses.\n */\nexport type PgliteFactory = (\n connectionString: string | undefined,\n) => PGliteType;\n\nexport interface DbClient {\n db: Db;\n knex: Knex;\n pglite: PGliteType | undefined;\n}\n\n/**\n * Cache of DB clients keyed by connection string. Reactor-api's read-model\n * layer wires analytics, attachments, and document-permissions as separate\n * consumers but they all target the same logical database (one postgres\n * instance, many schemas). Without caching:\n * - PGlite: two `new PGlite(samePath)` calls mean two embedded postgres\n * processes contending for the same data dir, racing shutdown syncs\n * and silently losing writes — a correctness bug.\n * - Postgres: each consumer opens an independent pool against the same\n * backend — wasteful but correct.\n * Caching by connection string returns the same knex/PGlite pair to every\n * consumer so writes coexist in one MemoryFS and one atomic snapshot, and\n * postgres callers get connection-pool dedup for free.\n *\n * Entries are evicted from inside the wrapped `knex.destroy()` below, so a\n * teardown + re-init in the same process (tests, hot-reloads) constructs\n * a fresh client instead of returning a closed pool.\n */\nconst IN_MEMORY_CACHE_KEY = Symbol(\"getDbClient:in-memory\");\ntype CacheKey = string | typeof IN_MEMORY_CACHE_KEY;\nconst dbClientCache = new Map<CacheKey, DbClient>();\n\nexport function getDbClient(\n connectionString: string | undefined = undefined,\n pgliteFactory?: PgliteFactory,\n): DbClient {\n const cacheKey: CacheKey = connectionString ?? IN_MEMORY_CACHE_KEY;\n const cached = dbClientCache.get(cacheKey);\n if (cached) return cached;\n\n const isPg = connectionString && isPG(connectionString);\n const client = isPg ? \"pg\" : (ClientPgLite as typeof knex.Client);\n const pgliteInstance: PGliteType | undefined = isPg\n ? undefined\n : pgliteFactory\n ? pgliteFactory(connectionString)\n : connectionString\n ? new PGlite({\n fs: new AtomicNodeFs(connectionString),\n parsers: PGLITE_UTC_PARSERS,\n })\n : new PGlite({ parsers: PGLITE_UTC_PARSERS });\n const connection = isPg ? { connectionString } : { pglite: pgliteInstance };\n\n // If path is not postgres then it is a filesystem path.\n // Ensures parent directory is created.\n if (connectionString && !isPg) {\n const dirPath = path.resolve(connectionString, \"..\");\n if (!fs.existsSync(dirPath)) {\n fs.mkdirSync(dirPath, { recursive: true });\n }\n }\n\n const knexInstance = knex({\n client,\n connection,\n });\n\n const kyselyInstance = new Kysely({\n dialect: new KyselyKnexDialect({\n knex: knexInstance,\n kyselySubDialect: new PGColdDialect(),\n }),\n });\n\n const dbClient: DbClient = {\n db: kyselyInstance,\n knex: knexInstance,\n pglite: pgliteInstance,\n };\n\n // Wrap knex.destroy so closing the client also drops the cache entry.\n // Works for both PGlite (which has a `closed` flag) and raw Postgres\n // pools (which don't), and keeps the Map from accumulating dead entries\n // when callers cycle through many distinct paths. `destroy` lives on\n // the Knex prototype as a read-only method, so use defineProperty to\n // shadow it on this instance.\n const originalDestroy = knexInstance.destroy.bind(knexInstance);\n Object.defineProperty(knexInstance, \"destroy\", {\n configurable: true,\n writable: true,\n value: async (...args: unknown[]) => {\n if (dbClientCache.get(cacheKey) === dbClient) {\n dbClientCache.delete(cacheKey);\n }\n return originalDestroy(...(args as []));\n },\n });\n\n dbClientCache.set(cacheKey, dbClient);\n return dbClient;\n}\n\nexport const initAnalyticsStoreSql = [\n `create table if not exists \"AnalyticsSeries\"\n (\n id serial primary key,\n source varchar(255) not null,\n start timestamp not null,\n \"end\" timestamp,\n metric varchar(255) not null,\n value real not null,\n unit varchar(255),\n fn varchar(255) not null,\n params json\n );`,\n `create unique index if not exists \"AnalyticsSeries_pkey\"\n on \"AnalyticsSeries\" (id);`,\n `create index if not exists analyticsseries_end_index\n on \"AnalyticsSeries\" (\"end\");`,\n `create index if not exists analyticsseries_fn_index\n on \"AnalyticsSeries\" (fn);`,\n `create index if not exists analyticsseries_metric_index\n on \"AnalyticsSeries\" (metric);`,\n `create index if not exists analyticsseries_source_index\n on \"AnalyticsSeries\" (source);`,\n `create index if not exists analyticsseries_start_index\n on \"AnalyticsSeries\" (start);`,\n `create index if not exists analyticsseries_unit_index\n on \"AnalyticsSeries\" (unit);`,\n `create index if not exists analyticsseries_value_index\n on \"AnalyticsSeries\" (value);`,\n `create table if not exists \"AnalyticsDimension\"\n (\n id serial primary key,\n dimension varchar(255) not null,\n path varchar(255) not null,\n label varchar(255),\n icon varchar(1000),\n description text\n );`,\n `create unique index if not exists \"AnalyticsDimension_pkey\"\n on \"AnalyticsDimension\" (id);`,\n `create index if not exists analyticsdimension_dimension_index\n on \"AnalyticsDimension\" (dimension);`,\n `create index if not exists analyticsdimension_path_index\n on \"AnalyticsDimension\" (path);`,\n `create table if not exists \"AnalyticsSeries_AnalyticsDimension\"\n (\n \"seriesId\" integer not null\n constraint analyticsseries_analyticsdimension_seriesid_foreign\n references \"AnalyticsSeries\"\n on delete cascade,\n \"dimensionId\" integer not null\n constraint analyticsseries_analyticsdimension_dimensionid_foreign\n references \"AnalyticsDimension\"\n on delete cascade\n );`,\n `create index if not exists analyticsseries_analyticsdimension_dimensionid_index\n on \"AnalyticsSeries_AnalyticsDimension\" (\"dimensionId\");`,\n `create index if not exists analyticsseries_analyticsdimension_seriesid_index\n on \"AnalyticsSeries_AnalyticsDimension\" (\"seriesId\");`,\n];\n","import type { PGlite } from \"@electric-sql/pglite\";\nimport type { IAnalyticsStore } from \"@powerhousedao/analytics-engine-core\";\nimport { PostgresAnalyticsStore } from \"@powerhousedao/analytics-engine-pg\";\nimport { getConfig } from \"@powerhousedao/config/node\";\nimport type {\n IDocumentModelRegistry,\n IDriveClient,\n IReadModel,\n IReactorClient,\n InProcessReactorModule,\n IProcessorManager as IReactorProcessorManager,\n ISyncManager,\n InProcessReactorClientModule,\n ProcessorRecord as ReactorProcessorRecord,\n} from \"@powerhousedao/reactor\";\nimport type { SyncScopeGate } from \"@powerhousedao/reactor\";\nimport {\n AttachmentBuilder,\n AttachmentReferenceIndexBuilder,\n} from \"@powerhousedao/reactor-attachments\";\nimport type {\n AttachmentBuildResult,\n AttachmentDatabase,\n AttachmentReferenceIndexBuildResult,\n IAttachmentReferenceWriter,\n} from \"@powerhousedao/reactor-attachments\";\nimport { createAttachmentClient } from \"@powerhousedao/reactor-attachments/client\";\nimport { setupMcpServer } from \"@powerhousedao/reactor-mcp\";\nimport type {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport type { Kysely } from \"kysely\";\nimport { mkdir } from \"node:fs/promises\";\nimport type http from \"node:http\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport type { Pool } from \"pg\";\nimport { WebSocketServer } from \"ws\";\nimport { createReactorHostModuleBase } from \"@powerhousedao/reactor\";\nimport {\n createRelationalDb,\n type IRelationalDb,\n type ProcessorApp,\n type ProcessorFactory,\n} from \"@powerhousedao/shared/processors\";\nimport { childLogger, type ILogger } from \"document-model\";\nimport { config, DefaultCoreSubgraphs } from \"./config.js\";\nimport { createStartupAttachmentBackend } from \"./attachment-backend.js\";\nimport {\n AttachmentAccessService,\n type AttachmentReferenceProjectionCapability,\n type IAttachmentAccessService,\n} from \"./services/attachment-access.service.js\";\nimport { createCanonicalDocumentIdResolver } from \"./services/canonical-document-id.js\";\nimport { AuthSubgraph } from \"./graphql/auth/subgraph.js\";\nimport {\n createAuthFetchMiddleware,\n type AuthFetchMiddleware,\n} from \"./graphql/gateway/auth-middleware.js\";\nimport {\n createGatewayAdapter,\n createHttpAdapter,\n type GatewayAdapterType,\n} from \"./graphql/gateway/factory.js\";\nimport {\n createRequireAuthFetchMiddleware,\n type RequireAuthFetchMiddleware,\n} from \"./graphql/gateway/require-auth-middleware.js\";\nimport type { IHttpAdapter, TlsOptions } from \"./graphql/gateway/types.js\";\nimport { GraphQLManager } from \"./graphql/graphql-manager.js\";\nimport {\n CORE_PACKAGE_NAME,\n HttpRouteService,\n RelationalWebhookStore,\n WEBHOOK_SEGMENT,\n WebhookService,\n} from \"./http/index.js\";\nimport {\n decodeExplorerUrlState,\n renderGraphqlPlayground,\n} from \"./graphql/playground.js\";\nimport { ReactorSubgraph } from \"./graphql/reactor/subgraph.js\";\nimport type { SubgraphClass } from \"./graphql/types.js\";\nimport { runMigrations } from \"./migrations/index.js\";\nimport { ImportPackageLoader } from \"./packages/import-loader.js\";\nimport {\n getUniqueDocumentModels,\n PackageManager,\n} from \"./packages/package-manager.js\";\nimport {\n AuthService,\n type CredentialVerifier,\n} from \"./services/auth.service.js\";\nimport { createRenownCredentialVerifier } from \"./services/renown-credential-verifier.js\";\nimport type {\n AuthorizationConfig,\n IAuthorizationService,\n} from \"./services/authorization.service.js\";\nimport {\n AuthorizationPolicy,\n createAuthorizationService,\n} from \"./services/authorization.service.js\";\nimport { DocumentPermissionService } from \"./services/document-permission.service.js\";\nimport { createGetParentIdsFn } from \"./services/get-parent-ids.js\";\nimport { createMcpRequestAuthorizer } from \"./services/mcp-request-authorizer.js\";\nimport { buildSyncServingGate } from \"./services/sync-serving-gate.js\";\nimport {\n assertCredentialVerifierForSource,\n resolveRenownConfig,\n type RenownConfig,\n type ResolvedRenownConfig,\n} from \"./services/renown-config.js\";\nimport type {\n API,\n IPackageLoader,\n IProcessorHostModule,\n Processor,\n ProcessorFactoryBuilder,\n ReadinessGate,\n} from \"./types.js\";\nimport {\n getDbClient,\n initAnalyticsStoreSql,\n type DocumentPermissionDatabase,\n type PgliteFactory,\n} from \"./utils/db.js\";\n\nconst defaultLogger = childLogger([\"reactor-api\", \"server\"]);\n\ntype Options = {\n port?: number;\n dbPath: string | undefined;\n client?: PGlite | typeof Pool | undefined;\n /**\n * Factory for the PGLite instance backing the read-model store. When set,\n * `getDbClient` uses it instead of constructing `new PGlite(dbPath)`. Used\n * by Switchboard to keep a legacy-version data dir readable while running\n * the newer Switchboard binary.\n */\n pgliteFactory?: PgliteFactory;\n configFile?: string;\n packages?: string[];\n auth?: {\n enabled: boolean;\n admins: string[];\n /** Read the bearer and populate `ctx.user` independently of `enabled`.\n * Defaults to `enabled`; `RESOLVE_CALLER_IDENTITY` overrides either. */\n resolveIdentity?: boolean;\n /** Reject anonymous callers with a 401 before any subgraph sees the\n * request. Off by default; `REQUIRE_AUTHENTICATED_CALLER` overrides.\n * Requires identity resolution to be on — refused at boot without it. */\n requireAuthenticatedCaller?: boolean;\n /** Mounted paths that stay reachable anonymously while\n * `requireAuthenticatedCaller` is on, for a flow that runs before\n * sign-in. Matched against the request's pathname in full, never as a\n * prefix. `REQUIRE_AUTHENTICATED_CALLER_EXEMPT_PATHS` overrides, as a\n * comma-separated list. Each entry is a hole in the floor: only ever name\n * a path serving operations that are safe without a caller. */\n requireAuthenticatedCallerExemptPaths?: string[];\n /** Decide an attachment read with the referencing document's own policy\n * instead of the host permission tables. Off by default;\n * `ATTACHMENT_READS_FOLLOW_DOCUMENT_POLICY` overrides. Requires auth\n * enforcement, which is what supplies the model — refused at boot\n * without it. */\n attachmentReadsFollowDocumentPolicy?: boolean;\n };\n /** Renown coordinates the host already resolved, used verbatim instead of\n * resolving `auth.renown` and the env again (which would warn twice). */\n renown?: ResolvedRenownConfig;\n /** Credential check replacing the built-in remote Renown one; required when\n * the resolved source is \"self\" (see assertCredentialVerifierForSource). */\n verifyCredential?: CredentialVerifier;\n https?:\n | {\n keyPath: string;\n certPath: string;\n }\n | boolean\n | undefined;\n packageLoaders?: IPackageLoader[];\n processors?: Record<string, ProcessorInitializer[]>;\n mcp?: boolean;\n processorConfig?: Map<string, unknown>;\n /**\n * Document permission service instance.\n * When provided, the Auth subgraph is registered and document permission\n * checks are enforced on document operations.\n * If not provided, can be auto-created by setting DOCUMENT_PERMISSIONS_ENABLED=true\n * environment variable.\n */\n documentPermissionService?: DocumentPermissionService;\n enableDocumentModelSubgraphs?: boolean;\n logger?: ILogger;\n /**\n * Filesystem path for attachment binary storage.\n * Defaults to a sibling \"attachments\" directory next to dbPath,\n * or os.tmpdir() for in-memory DB deployments.\n */\n attachmentStoragePath?: string;\n};\n\ntype ProcessorInitializer = ProcessorFactoryBuilder;\n\nconst DEFAULT_PORT = 4000;\n\n/**\n * Doc-perms require auth: with auth off no `user` is ever resolved, so every\n * authorization check fails closed. Refuse to boot rather than run broken.\n */\nexport function assertAuthRequiredForDocumentPermissions(\n authEnabled: boolean,\n documentPermissionsRequested: boolean,\n): void {\n if (!authEnabled && documentPermissionsRequested) {\n throw new Error(\n \"Document permissions require authentication: AUTH_ENABLED is false but \" +\n \"document permissions were requested (DOCUMENT_PERMISSIONS_ENABLED=true \" +\n \"or a documentPermissionService was provided). Enable authentication \" +\n \"(AUTH_ENABLED=true, or auth.enabled in the config file) or disable \" +\n \"document permissions.\",\n );\n }\n}\n\n/**\n * Refuses SKIP_CREDENTIAL_VERIFICATION at boot outside tests or an explicit\n * opt-in: it removes the only binding between a token's claimed address and its\n * signing key. Fail-closed — unset NODE_ENV counts as production.\n */\nexport function assertSkipCredentialVerificationAllowed(\n resolvesCallerIdentity: boolean,\n skipCredentialVerification: boolean,\n env: NodeJS.ProcessEnv,\n): void {\n if (!resolvesCallerIdentity || !skipCredentialVerification) {\n return;\n }\n const inAutomatedTest = env.VITEST === \"true\" || env.NODE_ENV === \"test\";\n const acknowledged =\n env.ALLOW_INSECURE_SKIP_CREDENTIAL_VERIFICATION === \"true\";\n if (!inAutomatedTest && !acknowledged) {\n throw new Error(\n \"SKIP_CREDENTIAL_VERIFICATION is set but refused: it disables the live \" +\n \"Renown credential check — the only check binding a token's claimed \" +\n \"address to the key that signed it — so honoring it allows identity \" +\n \"spoofing, including of admins. It is never safe in production. For \" +\n \"local or sandbox use, also set \" +\n \"ALLOW_INSECURE_SKIP_CREDENTIAL_VERIFICATION=true to acknowledge the \" +\n \"risk; automated test runs (VITEST=true or NODE_ENV=test) are exempt.\",\n );\n }\n}\n\n/**\n * Requiring an authenticated caller requires identity resolution to exist at\n * all: with neither AUTH_ENABLED nor RESOLVE_CALLER_IDENTITY the middleware\n * never reads a bearer, no `user` is ever resolved, and the\n * require-authenticated-caller middleware would reject every caller —\n * authenticated ones included. Refuse to boot rather than run broken.\n */\nexport function assertRequireAuthenticatedCallerAllowed(\n requireAuthenticatedCaller: boolean,\n resolvesCallerIdentity: boolean,\n exemptPaths: readonly string[] = [],\n): void {\n /**\n * An exemption is only ever a hole in this floor, so configuring one while\n * the floor is off is not a harmless no-op: it reads, to anyone auditing the\n * configuration, as a surface that was deliberately opened — and therefore\n * as a floor that exists. Refuse rather than let the two drift.\n */\n if (!requireAuthenticatedCaller && exemptPaths.length > 0) {\n throw new Error(\n \"REQUIRE_AUTHENTICATED_CALLER_EXEMPT_PATHS is set but refused: \" +\n \"REQUIRE_AUTHENTICATED_CALLER is off, so nothing is being exempted \" +\n \"from anything and the configuration claims a protection the server \" +\n \"is not applying. Enable the floor, or drop the exemptions.\",\n );\n }\n\n /**\n * A path that cannot match anything is worse than no path: the operator\n * believes the flow is reachable, and finds out when the first user cannot\n * claim an invitation. `URL.pathname` is always absolute, so an entry that\n * does not start with `/` never matches, whatever the router does.\n */\n const relative = exemptPaths.filter((path) => !path.trim().startsWith(\"/\"));\n if (relative.length > 0) {\n throw new Error(\n `REQUIRE_AUTHENTICATED_CALLER_EXEMPT_PATHS contains ${relative\n .map((path) => `\"${path}\"`)\n .join(\", \")}, which cannot match: an exempt path is compared against ` +\n \"the request's pathname and must start with '/' (for example \" +\n \"'/graphql/public').\",\n );\n }\n\n if (!requireAuthenticatedCaller || resolvesCallerIdentity) {\n return;\n }\n throw new Error(\n \"REQUIRE_AUTHENTICATED_CALLER is set but refused: it rejects every \" +\n \"request without a resolved caller, and with neither AUTH_ENABLED nor \" +\n \"RESOLVE_CALLER_IDENTITY the server never reads a bearer, so it would \" +\n \"reject every caller, including authenticated ones. Enable identity \" +\n \"resolution first (RESOLVE_CALLER_IDENTITY=true or AUTH_ENABLED=true).\",\n );\n}\n\n/**\n * Deciding an attachment read by the document's policy needs a policy model to\n * decide with, and that is what auth enforcement supplies. Without one there is\n * nothing to consult, so the setting would silently leave the permission tables\n * in charge — configuration that describes a protection the server is not\n * applying, which is worse than no configuration at all. Refuse instead.\n */\nexport function assertAttachmentPolicyReadsAllowed(\n attachmentReadsFollowDocumentPolicy: boolean,\n hasDecisionModel: boolean,\n): void {\n if (!attachmentReadsFollowDocumentPolicy || hasDecisionModel) {\n return;\n }\n throw new Error(\n \"ATTACHMENT_READS_FOLLOW_DOCUMENT_POLICY is set but refused: deciding an \" +\n \"attachment read by the referencing document's policy requires a policy \" +\n \"model to evaluate, and this composition has none, so the host \" +\n \"permission tables would keep deciding while the configuration says \" +\n \"otherwise. Enable auth enforcement first (REACTOR_AUTH_ENFORCEMENT=true).\",\n );\n}\n\nfunction createReadinessGate(): ReadinessGate {\n let ready = false;\n return {\n isReady: () => ready,\n markReady: () => {\n ready = true;\n },\n };\n}\n\n/**\n * The GraphiQL explorer page's mount prefix. `path.posix.join` normalizes the\n * join with `basePath` — a naive template literal would produce `//explorer`\n * for the default `/` basePath, which express compiles into a route that only\n * matches `//explorer`, leaving `GET /explorer` a 404.\n */\nexport function getExplorerPrefix(basePath: string): string {\n return path.posix.join(basePath, \"explorer\");\n}\n\nfunction resolveAttachmentStoragePath(options: Options): string {\n if (options.attachmentStoragePath) return options.attachmentStoragePath;\n if (options.dbPath && !options.dbPath.startsWith(\"postgres\")) {\n return path.resolve(options.dbPath, \"..\", \"attachments\");\n }\n return path.join(tmpdir(), \"reactor-attachments\");\n}\n\n/**\n * Initializes the database and analytics store. The returned `closers` are\n * idempotent thunks that release the underlying knex pool and PGlite instance\n * (when on-disk PGlite is in use); callers are expected to run them as part\n * of API teardown so PGlite WAL is flushed and the data-dir lock is released.\n */\nasync function initializeDatabaseAndAnalytics(\n dbPath: string | undefined,\n pgliteFactory: PgliteFactory | undefined,\n): Promise<{\n relationalDb: IRelationalDb;\n analyticsStore: IAnalyticsStore;\n closers: Array<() => Promise<void>>;\n}> {\n const { db, knex, pglite } = getDbClient(dbPath, pgliteFactory);\n const relationalDb = createRelationalDb<unknown>(db);\n const analyticsStore = new PostgresAnalyticsStore({\n knex,\n });\n\n for (const sql of initAnalyticsStoreSql) {\n await knex.raw(sql);\n }\n\n return {\n relationalDb,\n analyticsStore,\n closers: makeDbClosers(knex, pglite),\n };\n}\n\n/**\n * Builds best-effort closers for a knex/PGlite pair returned by\n * {@link getDbClient}. Order is significant: knex first releases its pool\n * (which is what the application talks to), then PGlite flushes WAL and\n * unlocks the data dir.\n */\nfunction makeDbClosers(\n knexInstance: { destroy: () => Promise<void> },\n pglite: PGlite | undefined,\n): Array<() => Promise<void>> {\n const closers: Array<() => Promise<void>> = [() => knexInstance.destroy()];\n if (pglite) {\n closers.push(async () => {\n if (!pglite.closed) await pglite.close();\n });\n }\n return closers;\n}\n\n/**\n * Resolves the gateway adapter type from the `GATEWAY_ADAPTER` env var.\n * Defaults to \"apollo\" (the federation gateway, production behavior).\n * \"stitching\" selects the in-process graphql-tools merge gateway (#1565\n * prototype); \"mercurius\" the Fastify federation gateway.\n */\nfunction resolveGatewayAdapterType(logger: ILogger): GatewayAdapterType {\n const configured = process.env.GATEWAY_ADAPTER;\n if (configured === undefined) {\n return \"apollo\";\n }\n if (\n configured === \"apollo\" ||\n configured === \"mercurius\" ||\n configured === \"stitching\"\n ) {\n return configured;\n }\n logger.warn(\n `Unknown GATEWAY_ADAPTER=\"${configured}\"; falling back to \"apollo\"`,\n );\n return \"apollo\";\n}\n\n/**\n * Sets up the subgraph manager and registers subgraphs\n */\nasync function setupGraphQLManager(\n httpAdapter: IHttpAdapter,\n authFetchMiddleware: AuthFetchMiddleware | undefined,\n requireAuthFetchMiddleware: RequireAuthFetchMiddleware | undefined,\n httpServer: http.Server,\n wsServer: WebSocketServer,\n client: IReactorClient,\n relationalDb: IRelationalDb,\n analyticsStore: IAnalyticsStore,\n syncManager: ISyncManager,\n subgraphs: {\n extended: Map<string, SubgraphClass[]>;\n core: SubgraphClass[];\n },\n logger: ILogger,\n authorizationService: IAuthorizationService,\n authService?: AuthService,\n documentPermissionService?: DocumentPermissionService,\n enableDocumentModelSubgraphs?: boolean,\n port?: number,\n reactorDriveClient?: IDriveClient,\n syncServingGate?: SyncScopeGate,\n httpRoutes?: HttpRouteService,\n): Promise<GraphQLManager> {\n const graphqlManager = new GraphQLManager(\n config.basePath,\n httpServer,\n wsServer,\n client,\n relationalDb,\n analyticsStore,\n syncManager,\n logger,\n httpAdapter,\n await createGatewayAdapter(resolveGatewayAdapterType(logger), logger),\n authService,\n documentPermissionService,\n {\n enableDocumentModelSubgraphs,\n },\n port,\n authorizationService,\n reactorDriveClient,\n syncServingGate,\n httpRoutes,\n );\n\n await graphqlManager.init(\n subgraphs.core,\n authFetchMiddleware,\n requireAuthFetchMiddleware,\n );\n\n for (const [packageName, collection] of subgraphs.extended.entries()) {\n for (const subgraph of collection) {\n await graphqlManager.registerSubgraph(\n subgraph,\n \"graphql\",\n false,\n packageName,\n );\n }\n }\n\n await graphqlManager.updateRouter();\n\n return graphqlManager;\n}\n\n/**\n * Sets up event listeners for package manager changes\n */\nfunction setupEventListeners(\n pkgManager: PackageManager,\n graphqlManager: GraphQLManager,\n reactorProcessorManager: IReactorProcessorManager,\n moduleFor: (packageName: string) => IProcessorHostModule,\n documentModelRegistry?: IDocumentModelRegistry,\n): void {\n pkgManager.onDocumentModelsChange((packagedModels) => {\n if (documentModelRegistry) {\n // Replace each incoming type's whole version family: skipping types\n // that are already registered would never pick up a new version of a\n // versioned model (or regenerated code for an existing one), and\n // unregisterModules is type-scoped so partial re-registration would\n // drop sibling versions.\n const newModules = getUniqueDocumentModels(\n Object.values(packagedModels).flat(),\n );\n const incomingTypes = new Set(\n newModules.map((m) => m.documentModel.global.id),\n );\n if (incomingTypes.size > 0) {\n documentModelRegistry.unregisterModules(...incomingTypes);\n const results = documentModelRegistry.registerModules(...newModules);\n for (const result of results) {\n if (result.status === \"success\") {\n defaultLogger.info(\n `Registered document model: ${result.item.documentModel.global.id} v${result.item.version ?? 1}`,\n );\n } else {\n defaultLogger.error(\n `Failed to register document model: ${result.error.message}`,\n );\n }\n }\n }\n\n // Manifests change together with document models (they live under the\n // same document-models/ tree), so swap them here as well.\n const manifests = pkgManager.getUniqueUpgradeManifests();\n if (manifests.length > 0) {\n documentModelRegistry.unregisterUpgradeManifests(\n ...manifests.map((m) => m.documentType),\n );\n const manifestResults = documentModelRegistry.registerUpgradeManifests(\n ...manifests,\n );\n for (const result of manifestResults) {\n if (result.status === \"error\") {\n defaultLogger.error(\n `Failed to register upgrade manifest: ${result.error.message}`,\n );\n }\n }\n }\n }\n void graphqlManager.regenerateDocumentModelSubgraphs();\n });\n\n let knownSubgraphPackages = new Set<string>();\n pkgManager.onSubgraphsChange((packagedSubgraphs) => {\n void (async () => {\n for (const [packageName, subgraphs] of packagedSubgraphs) {\n const incomingNames = new Set<string>();\n for (const subgraph of subgraphs) {\n const instance = await graphqlManager.registerSubgraph(\n subgraph,\n \"graphql\",\n false,\n packageName,\n );\n // Registration returns undefined when the subgraph is rejected\n // (e.g. its name is reserved by a core subgraph, issue #2972).\n // Nothing was mounted, so the name is not provided and must not\n // shield a stale same-named subgraph from being pruned below.\n if (!instance) {\n continue;\n }\n incomingNames.add(instance.name);\n }\n // The package is still loaded but dropped some (or all) of its\n // subgraphs: tear down the ones it no longer provides.\n await graphqlManager.prunePackageSubgraphs(packageName, incomingNames);\n }\n // A package that vanished from the map entirely (uninstalled or\n // removed from the config) keeps none of its subgraphs.\n for (const packageName of knownSubgraphPackages) {\n if (!packagedSubgraphs.has(packageName)) {\n await graphqlManager.unregisterPackage(packageName);\n }\n }\n knownSubgraphPackages = new Set(packagedSubgraphs.keys());\n await graphqlManager.updateRouter();\n })();\n });\n\n let knownProcessorPackages = new Set<string>();\n pkgManager.onProcessorsChange((processors) => {\n void (async () => {\n // Packages that vanished from the map entirely keep none of their\n // factories: unregister the leftovers.\n for (const packageName of knownProcessorPackages) {\n if (!processors.has(packageName)) {\n await reactorProcessorManager.unregisterFactory(packageName);\n }\n }\n knownProcessorPackages = new Set(processors.keys());\n\n for (const [packageName, fns] of processors) {\n await reactorProcessorManager.unregisterFactory(packageName);\n\n const factories = fns.map((fn) => fn(moduleFor(packageName)));\n\n const validBuilders = factories.filter(\n (factory): factory is ProcessorFactory =>\n typeof factory === \"function\",\n );\n\n if (!validBuilders.length) {\n continue;\n }\n\n await reactorProcessorManager.registerFactory(\n packageName,\n async (driveHeader) =>\n (\n await Promise.all(\n validBuilders.map(async (driveFactory) => {\n try {\n const result = await driveFactory(driveHeader);\n return result as unknown as ReactorProcessorRecord[];\n } catch (e) {\n const logger = defaultLogger;\n logger.error(\n `Error creating processor for drive ${driveHeader.id}:`,\n e,\n );\n return [];\n }\n }),\n )\n ).flat(),\n );\n }\n })();\n });\n}\n\n/**\n * Starts the server (HTTP or HTTPS) and attaches WebSocket server\n */\nasync function startServer(\n httpAdapter: IHttpAdapter,\n port: number,\n httpsOptions: Options[\"https\"],\n logger: ILogger,\n): Promise<{ httpServer: http.Server; wsServer: WebSocketServer }> {\n const tls: TlsOptions | undefined =\n httpsOptions === true\n ? true\n : typeof httpsOptions === \"object\"\n ? { keyPath: httpsOptions.keyPath, certPath: httpsOptions.certPath }\n : undefined;\n\n const httpServer = await httpAdapter.listen(port, tls);\n\n const wsServer = new WebSocketServer({\n server: httpServer,\n path: \"/graphql/subscriptions\",\n });\n\n logger.info(\"WebSocket server available at /graphql/subscriptions\");\n\n return { httpServer, wsServer };\n}\n\n/**\n * Private helper function that sets up common infrastructure before API initialization.\n * This includes auth configuration, database setup, and package manager initialization.\n */\nasync function _setupCommonInfrastructure(options: Options): Promise<{\n port: number;\n httpAdapter: IHttpAdapter;\n authFetchMiddleware: AuthFetchMiddleware | undefined;\n requireAuthFetchMiddleware: RequireAuthFetchMiddleware | undefined;\n authService: AuthService | undefined;\n relationalDb: IRelationalDb;\n analyticsStore: IAnalyticsStore;\n documentPermissionService: DocumentPermissionService | undefined;\n authorizationConfig: AuthorizationConfig;\n attachments: AttachmentBuildResult;\n attachmentReferenceIndex: AttachmentReferenceIndexBuildResult;\n packages: PackageManager;\n dbClosers: Array<() => Promise<void>>;\n readiness: ReadinessGate;\n httpRoutes: HttpRouteService;\n attachmentReadsFollowDocumentPolicy: boolean;\n}> {\n const port = options.port ?? DEFAULT_PORT;\n const { adapter: httpAdapter } = await createHttpAdapter(\"express\");\n const logger = options.logger ?? defaultLogger;\n\n // Setup auth configuration\n let admins: string[] = [];\n let authEnabled = false;\n let configuredResolveIdentity: boolean | undefined;\n let configuredRequireAuth: boolean | undefined;\n let configuredExemptPaths: string[] | undefined;\n let configuredAttachmentPolicyReads: boolean | undefined;\n let configuredRenown: RenownConfig | undefined;\n if (options.configFile) {\n const config = getConfig(options.configFile);\n admins = config.auth?.admins.map((a) => a.toLowerCase()) ?? [];\n authEnabled = config.auth?.enabled ?? false;\n configuredRenown = config.auth?.renown;\n } else if (options.auth) {\n admins = options.auth.admins.map((a) => a.toLowerCase());\n authEnabled = options.auth.enabled;\n configuredResolveIdentity = options.auth.resolveIdentity;\n configuredRequireAuth = options.auth.requireAuthenticatedCaller;\n configuredExemptPaths = options.auth.requireAuthenticatedCallerExemptPaths;\n configuredAttachmentPolicyReads =\n options.auth.attachmentReadsFollowDocumentPolicy;\n }\n const {\n AUTH_ENABLED,\n RESOLVE_CALLER_IDENTITY,\n REQUIRE_AUTHENTICATED_CALLER,\n REQUIRE_AUTHENTICATED_CALLER_EXEMPT_PATHS,\n ATTACHMENT_READS_FOLLOW_DOCUMENT_POLICY,\n ADMINS,\n DEFAULT_PROTECTION,\n DOCUMENT_PERMISSIONS_ENABLED,\n SKIP_CREDENTIAL_VERIFICATION,\n CREDENTIAL_VERIFICATION_CACHE_TTL_MS,\n } = process.env;\n if (AUTH_ENABLED !== undefined) {\n authEnabled = AUTH_ENABLED === \"true\";\n }\n\n /**\n * Whether the auth middleware reads the bearer and populates `ctx.user`,\n * independently of the authorization policy.\n *\n * Defaults to `authEnabled`, so a deployment that never sets it behaves\n * exactly as it did: auth on means the token is read AND the policy is\n * `ADMIN_ONLY`; auth off means neither. Setting it explicitly is what\n * separates the two — a server can then know who is calling while the policy\n * stays `OPEN`, which is the combination custom subgraphs need and the one\n * `AUTH_ENABLED` alone cannot express.\n */\n let resolveCallerIdentity = configuredResolveIdentity ?? authEnabled;\n if (RESOLVE_CALLER_IDENTITY !== undefined) {\n resolveCallerIdentity = RESOLVE_CALLER_IDENTITY === \"true\";\n }\n\n /**\n * Whether the require-authenticated-caller middleware is active: anonymous\n * callers are rejected with a 401 before any subgraph sees the request.\n *\n * Off by default, so nothing changes for existing deployments. This is the\n * enforcement half of the `RESOLVE_CALLER_IDENTITY` split: that one lets a\n * server know who is calling while the policy stays `OPEN`, and this one\n * closes the hole it leaves open — under `OPEN`, an anonymous caller\n * reaches the whole generic surface (document CRUD, sync, every custom\n * subgraph), because `OpenAuthorizationService` answers `true` to\n * everything. `ADMIN_ONLY` is the only alternative today, and it locks\n * out every non-admin; this expresses \"authenticated callers allowed,\n * anonymous not\".\n */\n let requireAuthenticatedCaller = configuredRequireAuth ?? false;\n if (REQUIRE_AUTHENTICATED_CALLER !== undefined) {\n requireAuthenticatedCaller = REQUIRE_AUTHENTICATED_CALLER === \"true\";\n }\n\n /**\n * The paths the floor above does not apply to. Comma-separated, like\n * `ADMINS`, because a deployment configures this the same way it configures\n * everything else: one variable, one line, however many values it has.\n *\n * Empty entries are dropped rather than refused, so a trailing comma or a\n * value split across lines in a manifest is not a boot failure; a value that\n * cannot ever match is refused, in\n * {@link assertRequireAuthenticatedCallerAllowed}.\n */\n let requireAuthenticatedCallerExemptPaths = configuredExemptPaths ?? [];\n if (REQUIRE_AUTHENTICATED_CALLER_EXEMPT_PATHS !== undefined) {\n requireAuthenticatedCallerExemptPaths =\n REQUIRE_AUTHENTICATED_CALLER_EXEMPT_PATHS.split(\",\")\n .map((path) => path.trim())\n .filter((path) => path.length > 0);\n }\n\n /**\n * Whether an attachment read is decided by the referencing document's own\n * policy rather than by the host's permission tables.\n *\n * Off by default, and a deployment's choice rather than something derived\n * from the flags around it. Which model governs those bytes is configuration\n * in the same sense the storage backend behind them is: a host that has said\n * nothing keeps exactly the behaviour it has, and one that wants the change\n * asks for it and can take it back without disturbing anything else.\n */\n let attachmentReadsFollowDocumentPolicy =\n configuredAttachmentPolicyReads ?? false;\n if (ATTACHMENT_READS_FOLLOW_DOCUMENT_POLICY !== undefined) {\n attachmentReadsFollowDocumentPolicy =\n ATTACHMENT_READS_FOLLOW_DOCUMENT_POLICY === \"true\";\n }\n\n if (ADMINS !== undefined) {\n admins = ADMINS.split(\",\").map((a) => a.toLowerCase());\n }\n\n let defaultProtection = false;\n if (DEFAULT_PROTECTION !== undefined) {\n defaultProtection = DEFAULT_PROTECTION.toLowerCase() === \"true\";\n }\n\n let skipCredentialVerification = false;\n if (SKIP_CREDENTIAL_VERIFICATION !== undefined) {\n skipCredentialVerification = SKIP_CREDENTIAL_VERIFICATION === \"true\";\n }\n\n let credentialVerificationCacheTtlMs: number | undefined;\n if (CREDENTIAL_VERIFICATION_CACHE_TTL_MS !== undefined) {\n const parsed = Number(CREDENTIAL_VERIFICATION_CACHE_TTL_MS);\n if (\n CREDENTIAL_VERIFICATION_CACHE_TTL_MS.trim() !== \"\" &&\n Number.isFinite(parsed) &&\n parsed >= 0\n ) {\n credentialVerificationCacheTtlMs = parsed;\n } else {\n logger.warn(\n `Ignoring invalid CREDENTIAL_VERIFICATION_CACHE_TTL_MS=\"${CREDENTIAL_VERIFICATION_CACHE_TTL_MS}\" (expected a non-negative number of milliseconds; 0 disables caching) — using the default TTL`,\n );\n }\n }\n\n const documentPermissionsRequested =\n options.documentPermissionService !== undefined ||\n DOCUMENT_PERMISSIONS_ENABLED === \"true\";\n assertAuthRequiredForDocumentPermissions(\n authEnabled,\n documentPermissionsRequested,\n );\n assertSkipCredentialVerificationAllowed(\n resolveCallerIdentity,\n skipCredentialVerification,\n process.env,\n );\n assertRequireAuthenticatedCallerAllowed(\n requireAuthenticatedCaller,\n resolveCallerIdentity,\n requireAuthenticatedCallerExemptPaths,\n );\n if (authEnabled && skipCredentialVerification) {\n logger.warn(\n \"SECURITY: SKIP_CREDENTIAL_VERIFICATION is enabled — Renown credential \" +\n \"verification is disabled and a bearer token's claimed address is NOT \" +\n \"cryptographically bound to its signing key. Identity is unverifiable; \" +\n \"use only in development or test.\",\n );\n }\n\n // Health check endpoint (registered directly on adapter, before auth)\n httpAdapter.getRoute(\"/health\", () => new Response(\"OK\", { status: 200 }));\n\n const readiness = createReadinessGate();\n httpAdapter.getRoute(\"/ready\", () =>\n readiness.isReady()\n ? new Response(\"OK\", { status: 200 })\n : new Response(\"starting\", { status: 503 }),\n );\n\n // Explorer route\n const explorerPrefix = getExplorerPrefix(config.basePath);\n httpAdapter.getRoute(`${explorerPrefix}/:endpoint?`, (request) => {\n const url = new URL(request.url);\n // Strip the prefix to find the optional :endpoint segment\n const suffix = url.pathname.slice(explorerPrefix.length).replace(/^\\//, \"\");\n const endpoint = suffix ? `/${suffix}` : \"/graphql\";\n // Prefer the document-scoped `explorerURLState` payload (produced by the\n // Connect DocumentToolbar) over the plain `?query=` parameter.\n const explorerState = decodeExplorerUrlState(\n url.searchParams.get(\"explorerURLState\") ?? \"\",\n );\n const query =\n explorerState?.query ?? url.searchParams.get(\"query\") ?? undefined;\n return new Response(\n renderGraphqlPlayground(\n endpoint,\n query,\n explorerState?.headers ?? {},\n explorerState?.variables,\n ),\n {\n headers: { \"Content-Type\": \"text/html\" },\n },\n );\n });\n\n /* Built whenever the bearer is read — which is not the same as the policy\n enforcing anything. `resolveCallerIdentity` defaults to `authEnabled`, so\n this is the same condition it always was unless a deployment opts in. */\n let authFetchMiddleware: AuthFetchMiddleware | undefined;\n let requireAuthFetchMiddleware: RequireAuthFetchMiddleware | undefined;\n let authService: AuthService | undefined;\n if (resolveCallerIdentity || authEnabled) {\n logger.info(\n \"Setting up Auth middleware (policy enforcement: @enabled, caller identity: @resolve)\",\n authEnabled,\n resolveCallerIdentity,\n );\n const renown =\n options.renown ??\n resolveRenownConfig(configuredRenown, process.env, logger);\n assertCredentialVerifierForSource(\n renown.source,\n options.verifyCredential !== undefined,\n );\n if (options.verifyCredential) {\n logger.info(\"Renown credentials will be verified by the host's verifier\");\n } else {\n logger.info(\n \"Renown credentials will be verified against @url\",\n renown.switchboardUrl ?? renown.url ?? \"the default Renown instance\",\n );\n }\n authService = new AuthService({\n enabled: authEnabled,\n resolveIdentity: resolveCallerIdentity,\n admins,\n skipCredentialVerification,\n credentialVerificationCacheTtlMs,\n verifyCredential:\n options.verifyCredential ??\n (await createRenownCredentialVerifier({\n renownUrl: renown.url,\n switchboardUrl: renown.switchboardUrl,\n })),\n });\n authFetchMiddleware = createAuthFetchMiddleware(authService);\n if (requireAuthenticatedCaller) {\n requireAuthFetchMiddleware = createRequireAuthFetchMiddleware(\n requireAuthenticatedCallerExemptPaths,\n );\n // The exempt paths are named in the log, not merely counted: the one\n // question an operator asks about this floor is what is still open, and\n // the answer should be in the boot output rather than in a manifest they\n // have to go and find.\n logger.info(\n requireAuthenticatedCallerExemptPaths.length > 0\n ? `Require-authenticated-caller middleware enabled: anonymous callers are rejected with a 401 before any subgraph, except on ${requireAuthenticatedCallerExemptPaths.join(\", \")}`\n : \"Require-authenticated-caller middleware enabled: anonymous callers are rejected with a 401 before any subgraph\",\n );\n } else {\n // Auth is on in some form, so say plainly what it is not doing. The\n // policy gates the reactor's own document reads; it does not gate a\n // package-provided subgraph, which authorizes nothing on its own. This\n // has always been true over HTTP, and WebSocket admission now matches it\n // rather than refusing tokenless connections on AUTH_ENABLED alone --\n // so a subscription reaches the same surface a query already did.\n logger.warn(\n \"Anonymous callers are admitted on every transport, including WebSocket \" +\n \"subscriptions: REQUIRE_AUTHENTICATED_CALLER is not set. The \" +\n \"authorization policy gates the reactor's own documents, but a \" +\n \"package-provided subgraph authorizes nothing on its own. Set \" +\n \"REQUIRE_AUTHENTICATED_CALLER=true to refuse anonymous callers before \" +\n \"any subgraph sees them.\",\n );\n }\n }\n\n const dbClosers: Array<() => Promise<void>> = [];\n\n // Initialize database and analytics store\n const {\n relationalDb,\n analyticsStore,\n closers: analyticsClosers,\n } = await initializeDatabaseAndAnalytics(\n options.dbPath,\n options.pgliteFactory,\n );\n dbClosers.push(...analyticsClosers);\n\n // Use provided document permission service, or create one if env var is set\n let documentPermissionService = options.documentPermissionService;\n if (!documentPermissionService && DOCUMENT_PERMISSIONS_ENABLED === \"true\") {\n const { db, knex, pglite } = getDbClient(\n options.dbPath,\n options.pgliteFactory,\n );\n dbClosers.push(...makeDbClosers(knex, pglite));\n // Run document permission migrations\n await runMigrations(db as Kysely<unknown>);\n logger.info(\"Document permission migrations completed\");\n documentPermissionService = new DocumentPermissionService(\n db as Kysely<DocumentPermissionDatabase>,\n { defaultProtection },\n );\n logger.info(\"Document permission service initialized\");\n }\n\n // The authorization policy collapses the prior dual enforcement paths into\n // one. Document permissions imply authentication (guaranteed by the boot\n // gate above). The service itself is created in _setupAPI, where the\n // reactor client needed for the parent-document resolver exists.\n const policy = documentPermissionService\n ? AuthorizationPolicy.DOCUMENT_PERMISSIONS\n : authEnabled\n ? AuthorizationPolicy.ADMIN_ONLY\n : AuthorizationPolicy.OPEN;\n const authorizationConfig: AuthorizationConfig = {\n admins,\n defaultProtection,\n policy,\n };\n\n // Initialize attachment service\n const attachmentStoragePath = resolveAttachmentStoragePath(options);\n await mkdir(attachmentStoragePath, { recursive: true });\n const {\n db: attachmentDb,\n knex: attachmentKnex,\n pglite: attachmentPglite,\n } = getDbClient(options.dbPath, options.pgliteFactory);\n dbClosers.push(...makeDbClosers(attachmentKnex, attachmentPglite));\n const ATTACHMENT_SWEEP_INTERVAL_MS = 60 * 60 * 1000; // hourly\n const attachmentBackend = await createStartupAttachmentBackend({\n db: attachmentDb as Kysely<AttachmentDatabase>,\n });\n const attachmentBuilder = new AttachmentBuilder(\n attachmentDb,\n attachmentStoragePath,\n ).withReservationSweepMs(ATTACHMENT_SWEEP_INTERVAL_MS);\n if (attachmentBackend) attachmentBuilder.withBackend(attachmentBackend);\n const attachments: AttachmentBuildResult = await attachmentBuilder.build();\n const attachmentReferenceIndex = await new AttachmentReferenceIndexBuilder(\n attachmentDb,\n ).build();\n dbClosers.push(() => {\n attachments.destroy();\n return Promise.resolve();\n });\n logger.info(\"Attachment service initialized\");\n\n // Initialize package manager\n const loaders: IPackageLoader[] = options.packageLoaders ?? [\n new ImportPackageLoader(),\n ];\n\n const packages = new PackageManager(loaders, {\n configFile: options.configFile,\n packages: options.packages ?? [],\n });\n\n // Package routes hang off <basePath>/api, webhooks off <basePath>/webhooks.\n // Created here rather than in the GraphQL manager because processors are\n // initialised before it exists.\n //\n // Webhook tokens live in the reactor's own database rather than per host, so\n // a URL a provider has registered keeps working across a restart and any\n // replica can serve it.\n const publicUrl = resolvePublicOrigin(port);\n const webhooks = new WebhookService({\n store: new RelationalWebhookStore(relationalDb),\n basePath: config.basePath,\n publicUrl,\n });\n const httpRoutes = new HttpRouteService({\n httpAdapter,\n basePath: config.basePath,\n authService,\n webhooks,\n publicUrl,\n // The reactor sits behind switchboard-lb in every deployed topology, so the\n // forwarded headers naming the public origin come from the balancer, not a caller.\n trustProxy: true,\n });\n // The endpoint family serves from a host scope rather than the adapter, so\n // one dispatch path covers package routes and webhooks alike.\n webhooks.attach(\n httpRoutes.hostScope(\n CORE_PACKAGE_NAME,\n path.posix.join(\"/\", config.basePath ?? \"/\", WEBHOOK_SEGMENT),\n ),\n );\n\n return {\n port,\n httpAdapter,\n httpRoutes,\n authFetchMiddleware,\n requireAuthFetchMiddleware,\n authService,\n relationalDb,\n analyticsStore,\n documentPermissionService,\n authorizationConfig,\n attachments,\n attachmentReferenceIndex,\n packages,\n dbClosers,\n readiness,\n attachmentReadsFollowDocumentPolicy,\n };\n}\n\n/**\n * Private helper function containing common setup logic for API initialization\n */\nasync function _setupAPI(\n reactorClient: IReactorClient,\n syncManager: ISyncManager,\n reactorProcessorManager: IReactorProcessorManager,\n httpAdapter: IHttpAdapter,\n authFetchMiddleware: AuthFetchMiddleware | undefined,\n requireAuthFetchMiddleware: RequireAuthFetchMiddleware | undefined,\n authService: AuthService | undefined,\n port: number,\n packages: PackageManager,\n relationalDb: IRelationalDb,\n analyticsStore: IAnalyticsStore,\n documentPermissionService: DocumentPermissionService | undefined,\n processors: Map<string, Processor>,\n subgraphs: Map<string, SubgraphClass[]>,\n options: Options,\n processorApp: ProcessorApp,\n readModels: IReadModel[],\n attachments: AttachmentBuildResult,\n attachmentReferenceIndex: AttachmentReferenceIndexBuildResult,\n attachmentReferenceProjection: AttachmentReferenceProjectionCapability,\n authorizationConfig: AuthorizationConfig,\n documentModelRegistry?: IDocumentModelRegistry,\n dbClosers: Array<() => Promise<void>> = [],\n reactorDriveClient?: IDriveClient,\n syncServingGate?: SyncScopeGate,\n httpRoutes?: HttpRouteService,\n attachmentReadsFollowDocumentPolicy = false,\n): Promise<API> {\n const hostModuleBase: IProcessorHostModule = {\n ...createReactorHostModuleBase({\n client: reactorClient,\n readModels,\n relationalDb,\n analyticsStore,\n processorApp,\n config: options.processorConfig,\n }),\n attachments: createAttachmentClient(attachments.service),\n };\n\n // Per package, so a processor's HTTP scope is bound to its own namespace and\n // cannot be swapped for another package's. Everything else is shared.\n const moduleFor = (packageName: string): IProcessorHostModule => ({\n ...hostModuleBase,\n http: httpRoutes?.scopeForOrNull(packageName),\n });\n const mcpServerEnabled = options.mcp ?? true;\n\n const logger = options.logger ?? defaultLogger;\n\n // initialize processors\n const configuredProcessorEntries = Object.entries(\n options.processors ?? {},\n ) as [string, ProcessorInitializer[]][];\n\n const processorEntries = [\n ...processors.entries(),\n ...configuredProcessorEntries,\n ] as [string, ProcessorInitializer[]][];\n\n for (const [packageName, fns] of processorEntries) {\n const factories = await Promise.allSettled(\n fns.map(async (fn) => {\n try {\n return fn(moduleFor(packageName));\n } catch (e) {\n logger.error(\n `Error initializing processor factory for package ${packageName}:`,\n e,\n );\n\n return null;\n }\n }),\n );\n\n const validFactories = factories.filter(\n (factory): factory is PromiseFulfilledResult<ProcessorFactory> =>\n factory.status === \"fulfilled\" &&\n factory.value !== null &&\n typeof factory.value === \"function\",\n );\n\n if (!validFactories.length) {\n continue;\n }\n\n // Register with the reactor ProcessorManager\n // Cast the results to ReactorProcessorRecord since the loaded factories\n // implement the reactor interface\n await reactorProcessorManager.registerFactory(\n packageName,\n async (driveHeader) =>\n (\n await Promise.all(\n validFactories.map(async ({ value: driveFactory }) => {\n try {\n const result = await driveFactory(driveHeader);\n return result as unknown as ReactorProcessorRecord[];\n } catch (e) {\n logger.error(\n `Error creating processor for drive ${driveHeader.id}:`,\n e,\n );\n\n return [];\n }\n }),\n )\n ).flat(),\n );\n }\n\n // Start the server\n const { httpServer, wsServer } = await startServer(\n httpAdapter,\n port,\n options.https,\n logger,\n );\n\n // Authorization service is always present; created here because the\n // parent-document resolver used for permission inheritance needs the\n // reactor client.\n const authorizationService = createAuthorizationService(\n authorizationConfig,\n documentPermissionService,\n createGetParentIdsFn(reactorClient),\n );\n logger.info(\n `Authorization service initialized (policy: ${authorizationConfig.policy})`,\n );\n\n // Attachment reads are authorized by the document read, the reactor's read\n // gate, and the projected document/ref relationship; the facade owns that\n // composition so routes never consult any of them directly.\n //\n // The document-read gate is the one sync serving already decides with, rather\n // than a second one built here: two gates over one document model would be\n // two policies that can disagree, and the question both are asking is the\n // same one — may this subject read this document's state.\n //\n // Handed over only when the host asks for it. Which model decides an\n // attachment read is a deployment's choice, the same way the storage backend\n // behind those bytes is, and a host that has not asked keeps the behaviour it\n // has — whatever else it has turned on.\n assertAttachmentPolicyReadsAllowed(\n attachmentReadsFollowDocumentPolicy,\n syncServingGate !== undefined,\n );\n const attachmentAccess: IAttachmentAccessService =\n new AttachmentAccessService(\n createCanonicalDocumentIdResolver(reactorClient),\n authorizationService,\n attachmentReferenceIndex.store,\n attachmentReferenceProjection,\n reactorClient,\n attachmentReadsFollowDocumentPolicy ? syncServingGate : undefined,\n );\n\n // set up subgraph manager\n const coreSubgraphs: SubgraphClass[] = DefaultCoreSubgraphs.slice();\n coreSubgraphs.push(ReactorSubgraph);\n\n // Register Auth subgraph when document permission service is available\n if (documentPermissionService) {\n coreSubgraphs.push(AuthSubgraph);\n logger.info(\"Auth subgraph registered (document permissions enabled)\");\n }\n\n const graphqlManager = await setupGraphQLManager(\n httpAdapter,\n authFetchMiddleware,\n requireAuthFetchMiddleware,\n httpServer,\n wsServer,\n reactorClient,\n relationalDb,\n analyticsStore,\n syncManager,\n {\n extended: subgraphs,\n core: coreSubgraphs,\n },\n logger.child([\"graphql-manager\"]),\n authorizationService,\n authService,\n documentPermissionService,\n options.enableDocumentModelSubgraphs,\n port,\n reactorDriveClient,\n syncServingGate,\n httpRoutes,\n );\n\n // Set up event listeners\n setupEventListeners(\n packages,\n graphqlManager,\n reactorProcessorManager,\n moduleFor,\n documentModelRegistry,\n );\n\n if (mcpServerEnabled) {\n await setupMcpServer(\n {\n client: reactorClient,\n syncManager,\n authorizeRequest: createMcpRequestAuthorizer(\n authService,\n authorizationService,\n ),\n },\n httpAdapter,\n );\n logger.info(`MCP server available at http://localhost:${port}/mcp`);\n }\n\n const dispose = buildApiDispose({\n graphqlManager,\n httpRoutes,\n httpServer,\n wsServer,\n dbClosers,\n logger,\n });\n\n return {\n httpAdapter,\n httpRoutes: httpRoutes ?? new HttpRouteService({ httpAdapter }),\n graphqlManager,\n packages,\n attachments,\n attachmentReferenceIndex,\n attachmentAccess,\n authService,\n // Read from the composed middleware rather than from a second pass over\n // the environment, and the same way `#makeWsContextFactory` reads it: the\n // middleware exists exactly when the floor is on, so one value cannot\n // disagree with another about whether this deployment serves anonymous\n // callers.\n requireAuthenticatedCaller: requireAuthFetchMiddleware !== undefined,\n // Handed back rather than kept private: a component the host composes\n // after boot (the workflow runtime) authorizes with this service and\n // stores in this database.\n authorizationService,\n relationalDb,\n dispose,\n };\n}\n\n/**\n * Composes the lifecycle teardown for an API instance. Steps run in\n * dependency order so that draining HTTP/GraphQL surfaces happens before the\n * underlying knex pool and PGlite WAL are released. Each step is wrapped in\n * its own try/catch — one failure must not strand the rest of the chain,\n * since this runs on the way to process exit.\n */\nfunction buildApiDispose(args: {\n graphqlManager: GraphQLManager;\n httpRoutes?: HttpRouteService;\n httpServer: http.Server;\n wsServer: WebSocketServer;\n dbClosers: Array<() => Promise<void>>;\n logger: ILogger;\n}): () => Promise<void> {\n const {\n graphqlManager,\n httpRoutes,\n httpServer,\n wsServer,\n dbClosers,\n logger,\n } = args;\n let disposed = false;\n return async () => {\n if (disposed) return;\n disposed = true;\n\n // Before the server closes: every package scope, and the host scopes with\n // them. Nothing downstream depends on the routes still being mounted, and\n // a handler answering during teardown is a handler holding a disposed\n // dependency.\n try {\n httpRoutes?.disposeAll();\n } catch (error) {\n logger.error(\"API dispose: releasing HTTP routes failed: @error\", error);\n }\n\n try {\n await graphqlManager.shutdown();\n } catch (error) {\n logger.error(\n \"API dispose: graphqlManager.shutdown failed: @error\",\n error,\n );\n }\n\n try {\n for (const client of wsServer.clients) client.terminate();\n await new Promise<void>((resolve) => wsServer.close(() => resolve()));\n } catch (error) {\n logger.error(\"API dispose: wsServer.close failed: @error\", error);\n }\n\n if (httpServer.listening) {\n try {\n // closeAllConnections forces idle keep-alives shut so close() can resolve;\n // otherwise SIGINT-driven shutdown stalls until the OS reaps the sockets.\n httpServer.closeAllConnections();\n await new Promise<void>((resolve, reject) =>\n httpServer.close((err) => (err ? reject(err) : resolve())),\n );\n } catch (error) {\n logger.error(\"API dispose: httpServer.close failed: @error\", error);\n }\n }\n\n for (const close of dbClosers) {\n try {\n await close();\n } catch (error) {\n logger.error(\"API dispose: db closer failed: @error\", error);\n }\n }\n };\n}\n\n/**\n * Initializes and starts the API server using an initializer function.\n * This function first loads packages to get document models, then calls the initializer function\n * to create the reactor client module with the appropriate dependencies.\n *\n * @param clientInitializer - Initializer function that creates the reactor client module with document models.\n * @param options - Additional options for server configuration.\n *\n * @returns The API server components along with the created client instances.\n */\n/**\n * Result of a client initializer. `reactorDriveClient` is optionally returned\n * alongside the reactor module so resolvers can dispatch reactor-drive parent\n * ops to it; legacy switchboards omit it.\n */\nexport interface ClientInitializerResult {\n module: InProcessReactorClientModule;\n reactorDriveClient?: IDriveClient;\n attachmentReferenceProjection?: AttachmentReferenceProjectionCapability;\n}\n\nexport interface ClientInitializerDependencies {\n attachmentReferenceWriter: IAttachmentReferenceWriter;\n /** Upgrade manifests exported by the loaded packages, one per type. */\n upgradeManifests: UpgradeManifest<readonly number[]>[];\n}\n\nexport type { AttachmentReferenceProjectionCapability } from \"./services/attachment-access.service.js\";\n\nexport async function initializeAndStartAPI(\n clientInitializer: (\n documentModels: DocumentModelModule[],\n dependencies: ClientInitializerDependencies,\n ) => Promise<ClientInitializerResult>,\n options: Options,\n processorApp: ProcessorApp,\n): Promise<\n API & {\n client: IReactorClient;\n syncManager: ISyncManager;\n documentModelRegistry: IDocumentModelRegistry;\n readiness: ReadinessGate;\n attachmentReferenceProjection: AttachmentReferenceProjectionCapability;\n packageManager: PackageManager;\n }\n> {\n const {\n port,\n httpAdapter,\n httpRoutes,\n authFetchMiddleware,\n requireAuthFetchMiddleware,\n authService,\n relationalDb,\n analyticsStore,\n documentPermissionService,\n authorizationConfig,\n attachments,\n attachmentReferenceIndex,\n packages,\n dbClosers,\n readiness,\n attachmentReadsFollowDocumentPolicy,\n } = await _setupCommonInfrastructure(options);\n\n const { documentModels, upgradeManifests, processors, subgraphs } =\n await packages.init();\n\n const {\n module: reactorClientModule,\n reactorDriveClient,\n attachmentReferenceProjection = {\n status: \"unavailable\",\n reason: \"initializer-did-not-report\",\n },\n } = await clientInitializer(documentModels, {\n attachmentReferenceWriter: attachmentReferenceIndex.store,\n upgradeManifests,\n });\n\n // Extract client and syncManager from the module\n const reactorClient = reactorClientModule.client;\n\n const syncManager =\n reactorClientModule.reactorModule?.syncModule?.syncManager;\n if (!syncManager) {\n throw new Error(\n \"SyncManager not available from InProcessReactorClientModule\",\n );\n }\n\n const reactorProcessorManager =\n reactorClientModule.reactorModule?.processorManager;\n if (!reactorProcessorManager) {\n throw new Error(\n \"ProcessorManager not available from InProcessReactorClientModule\",\n );\n }\n\n const documentModelRegistry =\n reactorClientModule.reactorModule?.documentModelRegistry;\n if (!documentModelRegistry) {\n throw new Error(\n \"DocumentModelRegistry not available from InProcessReactorClientModule\",\n );\n }\n\n const readModelCoordinator =\n reactorClientModule.reactorModule?.readModelCoordinator;\n const readModels = readModelCoordinator?.readModels ?? [];\n\n const api = await _setupAPI(\n reactorClient,\n syncManager,\n reactorProcessorManager,\n httpAdapter,\n authFetchMiddleware,\n requireAuthFetchMiddleware,\n authService,\n port,\n packages,\n relationalDb,\n analyticsStore,\n documentPermissionService,\n processors,\n subgraphs,\n options,\n processorApp,\n readModels,\n attachments,\n attachmentReferenceIndex,\n attachmentReferenceProjection,\n authorizationConfig,\n documentModelRegistry,\n dbClosers,\n reactorDriveClient,\n buildSyncServingGate(\n reactorClientModule.reactorModule,\n authorizationConfig,\n options.logger ?? defaultLogger,\n ),\n httpRoutes,\n attachmentReadsFollowDocumentPolicy,\n );\n\n return {\n ...api,\n client: reactorClient,\n syncManager,\n documentModelRegistry,\n readiness,\n attachmentReferenceProjection,\n packageManager: packages,\n };\n}\n\n/**\n * The origin to advertise in a webhook URL.\n *\n * A provider is a third party: it has to be given something it can resolve, so\n * a relative path is not an option. The platform variables come first, then a\n * bare deploy domain, and finally the local origin — which is right for `ph\n * dev` behind a tunnel and, at worst, obviously wrong rather than silently\n * unusable.\n */\nfunction resolvePublicOrigin(port: number): string {\n const explicit = process.env.PUBLIC_URL ?? process.env.RENDER_EXTERNAL_URL;\n if (explicit) return withScheme(explicit);\n const domain = process.env.HEROKU_APP_DEFAULT_DOMAIN_NAME;\n if (domain) return withScheme(domain);\n return `http://localhost:${port}`;\n}\n\nfunction withScheme(origin: string): string {\n const trimmed = origin.replace(/\\/+$/, \"\");\n return /^https?:\\/\\//.test(trimmed) ? trimmed : `https://${trimmed}`;\n}\n","export interface InstalledPackageInfo {\n name: string;\n version?: string;\n registryUrl: string;\n installedAt: Date;\n documentTypes: string[];\n}\n\nexport interface IPackageStorage {\n get(name: string): Promise<InstalledPackageInfo | undefined>;\n getAll(): Promise<InstalledPackageInfo[]>;\n set(name: string, info: InstalledPackageInfo): Promise<void>;\n delete(name: string): Promise<boolean>;\n has(name: string): Promise<boolean>;\n}\n\nexport class InMemoryPackageStorage implements IPackageStorage {\n private packages = new Map<string, InstalledPackageInfo>();\n\n get(name: string): Promise<InstalledPackageInfo | undefined> {\n return Promise.resolve(this.packages.get(name));\n }\n\n getAll(): Promise<InstalledPackageInfo[]> {\n return Promise.resolve(Array.from(this.packages.values()));\n }\n\n set(name: string, info: InstalledPackageInfo): Promise<void> {\n this.packages.set(name, info);\n return Promise.resolve();\n }\n\n delete(name: string): Promise<boolean> {\n return Promise.resolve(this.packages.delete(name));\n }\n\n has(name: string): Promise<boolean> {\n return Promise.resolve(this.packages.has(name));\n }\n}\n","import type { IDocumentModelRegistry } from \"@powerhousedao/reactor\";\nimport type { DocumentModelModule } from \"@powerhousedao/shared/document-model\";\nimport { childLogger } from \"document-model\";\nimport type { HttpPackageLoader } from \"../packages/http-loader.js\";\nimport type { IPackageManager } from \"../packages/types.js\";\nimport {\n InMemoryPackageStorage,\n type IPackageStorage,\n type InstalledPackageInfo,\n} from \"./package-storage.js\";\n\nexport interface InstallPackageResult {\n package: InstalledPackageInfo;\n documentModelsLoaded: number;\n}\n\nexport interface PackageManagementServiceOptions {\n storage?: IPackageStorage;\n defaultRegistryUrl?: string;\n httpLoader?: HttpPackageLoader;\n documentModelRegistry?: IDocumentModelRegistry;\n packageManager?: IPackageManager;\n}\n\nexport class PackageManagementService {\n private readonly storage: IPackageStorage;\n private readonly defaultRegistryUrl?: string;\n private readonly httpLoader?: HttpPackageLoader;\n private readonly documentModelRegistry?: IDocumentModelRegistry;\n private readonly packageManager?: IPackageManager;\n private readonly logger = childLogger([\n \"reactor-api\",\n \"package-management-service\",\n ]);\n\n private onModelsChanged?: (models: DocumentModelModule[]) => void;\n private loadedModulesCache = new Map<string, DocumentModelModule[]>();\n\n constructor(options: PackageManagementServiceOptions = {}) {\n this.storage = options.storage ?? new InMemoryPackageStorage();\n this.defaultRegistryUrl = options.defaultRegistryUrl;\n this.httpLoader = options.httpLoader;\n this.documentModelRegistry = options.documentModelRegistry;\n this.packageManager = options.packageManager;\n }\n\n setOnModelsChanged(callback: (models: DocumentModelModule[]) => void): void {\n this.onModelsChanged = callback;\n }\n\n async installPackage(\n name: string,\n registryUrl?: string,\n ): Promise<InstallPackageResult> {\n const url = registryUrl ?? this.defaultRegistryUrl;\n if (!url) {\n throw new Error(\n \"No registry URL provided and no default registry URL configured\",\n );\n }\n\n if (!this.httpLoader) {\n throw new Error(\"HttpPackageLoader not configured\");\n }\n\n const existing = await this.storage.get(name);\n if (existing) {\n throw new Error(`Package ${name} is already installed`);\n }\n\n this.logger.info(\"Installing package @name from @url\", name, url);\n\n const models = await this.httpLoader.loadDocumentModels(name);\n const documentTypes = models.map((m) => m.documentModel.global.id);\n\n const packageInfo: InstalledPackageInfo = {\n name,\n registryUrl: url,\n installedAt: new Date(),\n documentTypes,\n };\n\n await this.storage.set(name, packageInfo);\n this.loadedModulesCache.set(name, models);\n\n if (this.documentModelRegistry) {\n const results = this.documentModelRegistry.registerModules(...models);\n for (const result of results) {\n if (result.status === \"error\") {\n this.logger.error(\n \"Failed to register document model: @error\",\n result.error.message,\n );\n }\n }\n }\n\n this.logger.info(\n \"Installed package @name with @count document models\",\n name,\n models.length,\n );\n\n this.triggerModelsChanged();\n\n return {\n package: packageInfo,\n documentModelsLoaded: models.length,\n };\n }\n\n async uninstallPackage(name: string): Promise<boolean> {\n const existing = await this.storage.get(name);\n if (!existing) {\n this.logger.warn(\"Package @name is not installed\", name);\n return false;\n }\n\n this.logger.info(\"Uninstalling package @name\", name);\n\n await this.storage.delete(name);\n this.loadedModulesCache.delete(name);\n\n if (this.httpLoader) {\n this.httpLoader.documentModelLoader.removeFromCache(name);\n }\n\n if (this.documentModelRegistry) {\n this.documentModelRegistry.unregisterModules(...existing.documentTypes);\n }\n\n if (this.packageManager) {\n // Drop the package from the manager's maps so the subgraph and\n // processor teardown listeners run for everything it registered.\n this.packageManager.removePackage(name);\n }\n\n this.triggerModelsChanged();\n\n this.logger.info(\"Uninstalled package @name\", name);\n return true;\n }\n\n async getInstalledPackages(): Promise<InstalledPackageInfo[]> {\n return this.storage.getAll();\n }\n\n async getInstalledPackage(\n name: string,\n ): Promise<InstalledPackageInfo | undefined> {\n return this.storage.get(name);\n }\n\n getAllLoadedModules(): DocumentModelModule[] {\n const allModules: DocumentModelModule[] = [];\n for (const modules of this.loadedModulesCache.values()) {\n allModules.push(...modules);\n }\n return allModules;\n }\n\n private triggerModelsChanged(): void {\n if (this.onModelsChanged) {\n const allModules = this.getAllLoadedModules();\n this.onModelsChanged(allModules);\n }\n }\n}\n"],"names":["schemaSource","resolvers.documentAccess","resolvers.userDocumentPermissions","resolvers.operationPermissions","resolvers.canExecuteOperation","resolvers.documentProtection","resolvers.setDocumentProtection","resolvers.transferDocumentOwnership","resolvers.grantDocumentPermission","resolvers.revokeDocumentPermission","resolvers.grantOperationPermission","resolvers.revokeOperationPermission","logger","DEFAULT_MAX_BODY_BYTES","logger","scalarsTypeDefs","typeDefs","z","PropagationMode","documentResolver","findDocumentsResolver","documentOutgoingRelationshipsResolver","documentIncomingRelationshipsResolver","createDocumentWithInitialStateResolver","createEmptyDocumentResolver","schemaSource","resolvers.installedPackages","resolvers.installedPackage","resolvers.installPackage","resolvers.uninstallPackage","actionObj","schemaSource","resolvers.documentOperations","resolvers.documentModels","resolvers.document","resolvers.documentOutgoingRelationships","resolvers.documentIncomingRelationships","resolvers.documentOutgoingRelationshipEdges","resolvers.documentIncomingRelationshipEdges","resolvers.findDocuments","resolvers.jobStatus","resolvers.evaluateActions","resolvers.collectHeldSyncOperations","resolvers.pollSyncEnvelopes","resolvers.createDocument","resolvers.createEmptyDocument","resolvers.execute","resolvers.executeAsync","resolvers.mutateDocument","resolvers.mutateDocumentAsync","resolvers.renameDocument","resolvers.setPreferredEditor","resolvers.addRelationship","resolvers.updateRelationship","resolvers.removeRelationship","resolvers.moveRelationship","resolvers.deleteDocument","resolvers.deleteDocuments","resolvers.touchChannel","resolvers.pushSyncEnvelopes","loadDocumentModelsUtil","loadSubgraphsUtil","loadProcessorsUtil","up","down","up","down","migration001","migration002","migration003"],"mappings":"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;;AAU5C,SAAgB,OAAU,WAAyB;CACjD,OAAO;EACL,kBACE,WACA,SACiC;GACjC,OAAO,UACL,2BACA,WACA,OACF;EACF;EACA,YACE,WACA,SAC2B;GAC3B,OAAO,UACL,qBACA,WACA,OACF;EACF;EACA,0BACE,WACA,SACyC;GACzC,OAAO,UAIL,mCACA,WACA,OACF;EACF;EACA,iCACE,WACA,SACgD;GAChD,OAAO,UAIL,0CACA,WACA,OACF;EACF;EACA,iCACE,WACA,SACgD;GAChD,OAAO,UAIL,0CACA,WACA,OACF;EACF;EACA,qCACE,WACA,SACoD;GACpD,OAAO,UAIL,8CACA,WACA,OACF;EACF;EACA,qCACE,WACA,SACoD;GACpD,OAAO,UAIL,8CACA,WACA,OACF;EACF;EACA,cACE,WACA,SAC6B;GAC7B,OAAO,UACL,uBACA,WACA,OACF;EACF;EACA,sBACE,WACA,SACqC;GACrC,OAAO,UAIL,+BACA,WACA,OACF;EACF;EACA,aACE,WACA,SAC4B;GAC5B,OAAO,UACL,sBACA,WACA,OACF;EACF;EACA,gBACE,WACA,SAC+B;GAC/B,OAAO,UACL,yBACA,WACA,OACF;EACF;EACA,eACE,WACA,SACiC;GACjC,OAAO,UACL,wBACA,WACA,OACF;EACF;EACA,oBACE,WACA,SACsC;GACtC,OAAO,UAIL,6BACA,WACA,OACF;EACF;EACA,eACE,WACA,SACiC;GACjC,OAAO,UACL,wBACA,WACA,OACF;EACF;EACA,oBACE,WACA,SACsC;GACtC,OAAO,UAIL,6BACA,WACA,OACF;EACF;EACA,eACE,WACA,SACiC;GACjC,OAAO,UACL,wBACA,WACA,OACF;EACF;EACA,mBACE,WACA,SACqC;GACrC,OAAO,UAIL,4BACA,WACA,OACF;EACF;EACA,gBACE,WACA,SACkC;GAClC,OAAO,UAIL,yBACA,WACA,OACF;EACF;EACA,mBACE,WACA,SACqC;GACrC,OAAO,UAIL,4BACA,WACA,OACF;EACF;EACA,mBACE,WACA,SACqC;GACrC,OAAO,UAIL,4BACA,WACA,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","debug_id":"69ff78c8-e6e1-5d53-97e4-a5e8a75417ed"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/graphql/analytics-subgraph.ts","../src/graphql/auth/schema.graphql","../src/graphql/auth/resolvers.ts","../src/graphql/auth/subgraph.ts","../src/graphql/gateway/auth-middleware.ts","../src/graphql/gateway/factory.ts","../src/graphql/gateway/types.ts","../src/http/namespace.ts","../src/http/node-response.ts","../src/http/route-service.ts","../src/http/webhook-verify.ts","../src/http/webhook-service.ts","../src/http/webhook-store.ts","../src/utils/create-schema.ts","../src/graphql/reactor/gen/graphql.ts","../src/graphql/reactor/adapters.ts","../src/graphql/reactor/constants.ts","../src/graphql/reactor/resolvers.ts","../src/graphql/document-model-subgraph.ts","../src/graphql/gateway/drive-middleware.ts","../src/graphql/gateway/drive-ownership-cache.ts","../src/graphql/sse.ts","../src/graphql/graphql-manager.ts","../src/graphql/packages/resolvers.ts","../src/graphql/packages/schema.graphql","../src/graphql/packages/subgraph.ts","../src/graphql/playground.ts","../src/graphql/reactor/requester.ts","../src/graphql/reactor/validation.ts","../src/graphql/reactor/requester.with-zod.ts","../src/graphql/reactor/factory.ts","../src/graphql/reactor/schema.graphql","../src/graphql/reactor/pubsub.ts","../src/graphql/reactor/subgraph.ts","../src/graphql/system/env/getters.ts","../src/graphql/system/env/index.ts","../src/graphql/system/version.ts","../src/graphql/system/subgraph.ts","../src/packages/http-loader.ts","../src/packages/import-loader.ts","../src/packages/package-manager.ts","../src/config.ts","../src/attachment-backend.ts","../src/services/attachment-access.service.ts","../src/graphql/gateway/require-auth-middleware.ts","../src/migrations/001_create_document_permissions.ts","../src/migrations/002_add_document_protection.ts","../src/migrations/003_remove_group_tables.ts","../src/migrations/index.ts","../src/services/auth.service.ts","../src/services/renown-credential-verifier.ts","../src/services/document-permission.service.ts","../src/services/get-parent-ids.ts","../src/services/mcp-request-authorizer.ts","../src/services/sync-serving-gate.ts","../src/services/renown-config.ts","../src/utils/db.ts","../src/server.ts","../src/services/package-storage.ts","../src/services/package-management.service.ts"],"sourcesContent":["import type { GraphQLResolverMap } from \"@apollo/subgraph\";\nimport type { IAnalyticsStore } from \"@powerhousedao/analytics-engine-core\";\nimport { AnalyticsQueryEngine } from \"@powerhousedao/analytics-engine-core\";\nimport {\n AnalyticsModel,\n AnalyticsResolvers,\n typedefs,\n} from \"@powerhousedao/analytics-engine-graphql\";\nimport type { Context, SubgraphArgs } from \"@powerhousedao/reactor-api\";\nimport { gql } from \"graphql-tag\";\nimport { BaseSubgraph } from \"./base-subgraph.js\";\nimport { AuthenticationRequiredError, ForbiddenError } from \"./errors.js\";\n\ntype AnalyticsResolver = (\n parent: unknown,\n args: unknown,\n ctx: Context,\n) => unknown;\n\nconst analyticsResolvers = AnalyticsResolvers as {\n Query: { analytics: AnalyticsResolver };\n} & Record<string, Record<string, AnalyticsResolver>>;\n\nexport class AnalyticsSubgraph extends BaseSubgraph {\n analyticsStore: IAnalyticsStore;\n analyticsModel: AnalyticsModel;\n\n name = \"analytics\";\n typeDefs = gql`\n ${typedefs}\n `;\n\n /**\n * Every analytics field hangs off `Query.analytics`, so gating it gates them\n * all. Series are aggregates a processor built from many documents and carry\n * no document to decide on, so only a caller with policy-wide read (anyone\n * under OPEN, an admin otherwise) may read them.\n */\n resolvers = {\n ...analyticsResolvers,\n Query: {\n ...analyticsResolvers.Query,\n analytics: (parent: unknown, args: unknown, ctx: Context) => {\n this.#assertCanReadAnalytics(ctx);\n return analyticsResolvers.Query.analytics(parent, args, ctx);\n },\n },\n } as GraphQLResolverMap<Context>;\n\n constructor(args: SubgraphArgs) {\n super(args);\n this.analyticsStore = args.analyticsStore;\n\n this.analyticsModel = new AnalyticsModel(\n new AnalyticsQueryEngine(this.analyticsStore),\n );\n\n args.graphqlManager.setAdditionalContextFields({\n dataSources: {\n db: {\n Analytics: this.analyticsModel,\n },\n },\n });\n }\n\n #assertCanReadAnalytics(ctx: Context): void {\n if (this.authorizationService.isSupremeAdmin(ctx.user?.address)) return;\n if (ctx.user?.address) {\n throw new ForbiddenError(\"to read analytics\");\n }\n throw new AuthenticationRequiredError(\"to read analytics\");\n }\n}\n","\"# 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\"","import { GraphQLError } from \"graphql\";\nimport type {\n CanonicalDocumentId,\n IAuthorizationService,\n} from \"../../services/authorization.service.js\";\nimport type { DocumentPermissionService } from \"../../services/document-permission.service.js\";\nimport type { DocumentPermissionLevel } from \"../../utils/db.js\";\n\n// ============================================\n// Document Permission Resolvers\n// ============================================\n\nexport type DocumentAccessInfo = {\n documentId: string;\n permissions: Array<{\n documentId: string;\n userAddress: string;\n permission: DocumentPermissionLevel;\n grantedBy: string;\n createdAt: Date;\n updatedAt: Date;\n }>;\n};\n\nexport async function documentAccess(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: { documentId: CanonicalDocumentId },\n userAddress: string | undefined,\n): Promise<DocumentAccessInfo> {\n if (!userAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n userAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to view its permissions\",\n );\n }\n\n const permissions = await service.getDocumentPermissions(args.documentId);\n\n return {\n documentId: args.documentId,\n permissions,\n };\n}\n\nexport async function userDocumentPermissions(\n service: DocumentPermissionService,\n userAddress: string,\n): Promise<\n Array<{\n documentId: string;\n userAddress: string;\n permission: DocumentPermissionLevel;\n grantedBy: string;\n createdAt: Date;\n updatedAt: Date;\n }>\n> {\n return service.getUserDocuments(userAddress);\n}\n\nexport async function grantDocumentPermission(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: {\n documentId: CanonicalDocumentId;\n userAddress: string;\n permission: DocumentPermissionLevel;\n },\n grantedByAddress: string | undefined,\n): Promise<{\n documentId: string;\n userAddress: string;\n permission: DocumentPermissionLevel;\n grantedBy: string;\n createdAt: Date;\n updatedAt: Date;\n}> {\n if (!grantedByAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n grantedByAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to grant permissions\",\n );\n }\n\n return service.grantPermission(\n args.documentId,\n args.userAddress,\n args.permission,\n grantedByAddress,\n );\n}\n\nexport async function revokeDocumentPermission(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: { documentId: CanonicalDocumentId; userAddress: string },\n revokedByAddress: string | undefined,\n): Promise<boolean> {\n if (!revokedByAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n revokedByAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to revoke permissions\",\n );\n }\n\n await service.revokePermission(args.documentId, args.userAddress);\n return true;\n}\n\n// ============================================\n// Operation Permission Resolvers\n// ============================================\n\nexport type OperationUserPermission = {\n documentId: string;\n operationType: string;\n userAddress: string;\n grantedBy: string;\n createdAt: Date;\n};\n\nexport type OperationPermissionsInfo = {\n documentId: string;\n operationType: string;\n userPermissions: OperationUserPermission[];\n};\n\nexport async function operationPermissions(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: { documentId: CanonicalDocumentId; operationType: string },\n userAddress: string | undefined,\n): Promise<OperationPermissionsInfo> {\n if (!userAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n userAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to view its operation permissions\",\n );\n }\n\n const userPermissions = await service.getOperationUserPermissions(\n args.documentId,\n args.operationType,\n );\n\n return {\n documentId: args.documentId,\n operationType: args.operationType,\n userPermissions,\n };\n}\n\nexport async function canExecuteOperation(\n authorizationService: IAuthorizationService,\n args: { documentId: CanonicalDocumentId; operationType: string },\n userAddress: string | undefined,\n): Promise<boolean> {\n return authorizationService.canMutate(\n args.documentId,\n args.operationType,\n userAddress,\n );\n}\n\nexport async function grantOperationPermission(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: {\n documentId: CanonicalDocumentId;\n operationType: string;\n userAddress: string;\n },\n grantedByAddress: string | undefined,\n): Promise<OperationUserPermission> {\n if (!grantedByAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n grantedByAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to grant operation permissions\",\n );\n }\n\n return service.grantOperationPermission(\n args.documentId,\n args.operationType,\n args.userAddress,\n grantedByAddress,\n );\n}\n\nexport async function revokeOperationPermission(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: {\n documentId: CanonicalDocumentId;\n operationType: string;\n userAddress: string;\n },\n revokedByAddress: string | undefined,\n): Promise<boolean> {\n if (!revokedByAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n revokedByAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to revoke operation permissions\",\n );\n }\n\n await service.revokeOperationPermission(\n args.documentId,\n args.operationType,\n args.userAddress,\n );\n return true;\n}\n\n// ============================================\n// Document Protection Resolvers\n// ============================================\n\nexport type DocumentProtectionInfo = {\n documentId: string;\n protected: boolean;\n ownerAddress: string | null;\n};\n\nexport async function documentProtection(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: { documentId: CanonicalDocumentId },\n userAddress: string | undefined,\n): Promise<DocumentProtectionInfo> {\n if (!userAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n userAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to view its protection info\",\n );\n }\n\n return service.getDocumentProtection(args.documentId);\n}\n\nexport async function setDocumentProtection(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: { documentId: CanonicalDocumentId; protected: boolean },\n userAddress: string | undefined,\n): Promise<DocumentProtectionInfo> {\n if (!userAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n userAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to change protection\",\n );\n }\n\n await service.setDocumentProtection(args.documentId, args.protected);\n return service.getDocumentProtection(args.documentId);\n}\n\nexport async function transferDocumentOwnership(\n service: DocumentPermissionService,\n authorizationService: IAuthorizationService,\n args: { documentId: CanonicalDocumentId; newOwnerAddress: string },\n userAddress: string | undefined,\n): Promise<DocumentProtectionInfo> {\n if (!userAddress) {\n throw new GraphQLError(\"Authentication required\");\n }\n\n const canManage = await authorizationService.canManage(\n args.documentId,\n userAddress,\n );\n if (!canManage) {\n throw new GraphQLError(\n \"Forbidden: You must be an admin of this document to transfer ownership\",\n );\n }\n\n // Revoke old owner's explicit ADMIN grant before transferring\n const previousOwner = await service.getDocumentOwner(args.documentId);\n if (previousOwner) {\n await service.revokePermission(args.documentId, previousOwner);\n }\n\n await service.setDocumentOwner(args.documentId, args.newOwnerAddress);\n\n // Grant ADMIN to new owner\n await service.grantPermission(\n args.documentId,\n args.newOwnerAddress,\n \"ADMIN\",\n userAddress,\n );\n\n return service.getDocumentProtection(args.documentId);\n}\n","import { ConsoleLogger } from \"document-model\";\nimport { GraphQLError } from \"graphql\";\nimport { gql } from \"graphql-tag\";\nimport schemaSource from \"./schema.graphql\";\nimport { BaseSubgraph } from \"../base-subgraph.js\";\nimport type { SubgraphArgs } from \"../types.js\";\nimport * as resolvers from \"./resolvers.js\";\n\n/**\n * Auth Subgraph - handles all document permission and authorization operations\n *\n * This subgraph is conditionally registered based on the DOCUMENT_PERMISSIONS_ENABLED\n * feature flag. When enabled, it provides GraphQL operations for:\n * - Document permissions (grant/revoke user access)\n * - Document protection and ownership\n * - Operation-level permissions (fine-grained operation control)\n */\nexport class AuthSubgraph extends BaseSubgraph {\n private logger = new ConsoleLogger([\"AuthSubgraph\"]);\n\n constructor(args: SubgraphArgs) {\n super(args);\n this.logger.verbose(`constructor()`);\n }\n\n name = \"auth\";\n hasSubscriptions = false;\n\n typeDefs = gql(schemaSource);\n\n resolvers = {\n Query: {\n documentAccess: async (\n _parent: unknown,\n args: { documentId: string },\n ctx: { user?: { address: string } },\n ) => {\n this.logger.debug(\"documentAccess(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.documentAccess(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in documentAccess: @error\", error);\n throw error;\n }\n },\n\n userDocumentPermissions: async (\n _parent: unknown,\n _args: unknown,\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"userDocumentPermissions\");\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n if (!ctx.user?.address) {\n return [];\n }\n try {\n return await resolvers.userDocumentPermissions(\n this.documentPermissionService,\n ctx.user.address,\n );\n } catch (error) {\n this.logger.error(\"Error in userDocumentPermissions: @error\", error);\n throw error;\n }\n },\n\n operationPermissions: async (\n _parent: unknown,\n args: { documentId: string; operationType: string },\n ctx: { user?: { address: string } },\n ) => {\n this.logger.debug(\"operationPermissions(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.operationPermissions(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in operationPermissions: @error\", error);\n throw error;\n }\n },\n\n canExecuteOperation: async (\n _parent: unknown,\n args: { documentId: string; operationType: string },\n ctx: { user?: { address: string } },\n ) => {\n this.logger.debug(\"canExecuteOperation(@args)\", args);\n try {\n return await resolvers.canExecuteOperation(\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in canExecuteOperation: @error\", error);\n throw error;\n }\n },\n\n documentProtection: async (\n _parent: unknown,\n args: { documentId: string },\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"documentProtection(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.documentProtection(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in documentProtection: @error\", error);\n throw error;\n }\n },\n },\n\n Mutation: {\n setDocumentProtection: async (\n _parent: unknown,\n args: { documentId: string; protected: boolean },\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"setDocumentProtection(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.setDocumentProtection(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in setDocumentProtection: @error\", error);\n throw error;\n }\n },\n\n transferDocumentOwnership: async (\n _parent: unknown,\n args: { documentId: string; newOwnerAddress: string },\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"transferDocumentOwnership(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.transferDocumentOwnership(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\n \"Error in transferDocumentOwnership: @error\",\n error,\n );\n throw error;\n }\n },\n\n grantDocumentPermission: async (\n _parent: unknown,\n args: { documentId: string; userAddress: string; permission: string },\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"grantDocumentPermission(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n const resolved = await this.withCanonicalDocumentId(args, ctx);\n return await resolvers.grantDocumentPermission(\n this.documentPermissionService,\n this.authorizationService,\n {\n ...resolved,\n permission: resolved.permission as \"READ\" | \"WRITE\" | \"ADMIN\",\n },\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in grantDocumentPermission: @error\", error);\n throw error;\n }\n },\n\n revokeDocumentPermission: async (\n _parent: unknown,\n args: { documentId: string; userAddress: string },\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"revokeDocumentPermission(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.revokeDocumentPermission(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in revokeDocumentPermission: @error\", error);\n throw error;\n }\n },\n\n // Operation Permission Mutations\n grantOperationPermission: async (\n _parent: unknown,\n args: {\n documentId: string;\n operationType: string;\n userAddress: string;\n },\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"grantOperationPermission(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.grantOperationPermission(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\"Error in grantOperationPermission: @error\", error);\n throw error;\n }\n },\n\n revokeOperationPermission: async (\n _parent: unknown,\n args: {\n documentId: string;\n operationType: string;\n userAddress: string;\n },\n ctx: {\n user?: { address: string };\n },\n ) => {\n this.logger.debug(\"revokeOperationPermission(@args)\", args);\n if (!this.documentPermissionService) {\n throw new GraphQLError(\"DocumentPermissionService not available\");\n }\n try {\n return await resolvers.revokeOperationPermission(\n this.documentPermissionService,\n this.authorizationService,\n await this.withCanonicalDocumentId(args, ctx),\n ctx.user?.address,\n );\n } catch (error) {\n this.logger.error(\n \"Error in revokeOperationPermission: @error\",\n error,\n );\n throw error;\n }\n },\n },\n };\n\n onSetup(): Promise<void> {\n this.logger.debug(\"Setting up AuthSubgraph\");\n return Promise.resolve();\n }\n}\n","import type { AuthContext, AuthService } from \"../../services/auth.service.js\";\nimport type { FetchHandler } from \"./types.js\";\n\nexport type AuthFetchMiddleware = (handler: FetchHandler) => FetchHandler;\n\nconst authContextMap = new WeakMap<globalThis.Request, AuthContext>();\n\n/** Internal — only `graphql-manager.ts` should call this. */\nexport function getAuthContext(\n request: globalThis.Request,\n): AuthContext | undefined {\n return authContextMap.get(request);\n}\n\nexport function createAuthFetchMiddleware(\n authService: AuthService,\n): AuthFetchMiddleware {\n return (next: FetchHandler): FetchHandler =>\n async (request: globalThis.Request): Promise<globalThis.Response> => {\n const result = await authService.authenticateRequest(request);\n if (result instanceof globalThis.Response) return result;\n authContextMap.set(request, result);\n return next(request);\n };\n}\n","import type { ILogger } from \"document-model\";\nimport type { Context } from \"../types.js\";\nimport type { IGatewayAdapter, IHttpAdapter } from \"./types.js\";\n\nexport type GatewayAdapterType = \"apollo\" | \"mercurius\" | \"stitching\";\nexport type HttpAdapterType = \"express\" | \"fastify\";\n\nexport async function createGatewayAdapter(\n type: GatewayAdapterType,\n logger: ILogger,\n): Promise<IGatewayAdapter<Context>> {\n switch (type) {\n case \"apollo\": {\n const { ApolloGatewayAdapter } =\n await import(\"./adapter-gateway-apollo.js\");\n return new ApolloGatewayAdapter(logger);\n }\n case \"mercurius\": {\n const { MercuriusGatewayAdapter } =\n await import(\"./adapter-gateway-mercurius.js\");\n return new MercuriusGatewayAdapter(logger);\n }\n case \"stitching\": {\n const { StitchingGatewayAdapter } =\n await import(\"./adapter-gateway-stitching.js\");\n return new StitchingGatewayAdapter(logger);\n }\n }\n}\n\nexport type HttpAdapterSetup = {\n adapter: IHttpAdapter;\n};\n\nexport async function createHttpAdapter(\n type: HttpAdapterType,\n): Promise<HttpAdapterSetup> {\n switch (type) {\n case \"express\": {\n const { createExpressHttpAdapter } =\n await import(\"./adapter-http-express.js\");\n return createExpressHttpAdapter();\n }\n case \"fastify\": {\n const { createFastifyHttpAdapter } =\n await import(\"./adapter-http-fastify.js\");\n return createFastifyHttpAdapter();\n }\n }\n}\n","import type { CorsOptions } from \"cors\";\nimport type { DocumentNode, GraphQLSchema } from \"graphql\";\nimport type http from \"node:http\";\nimport type { WebSocketServer } from \"ws\";\n\nexport type TlsOptions =\n | { keyPath: string; certPath: string }\n | { cert: Buffer | string; key: Buffer | string }\n | true;\n\n// Framework-agnostic context factory - receives the Fetch API Request for the current operation\nexport type GatewayContextFactory<TContext = unknown> = (\n request: Request,\n) => Promise<TContext>;\n\n// Opaque per-connection key carrying what `onConnect` resolved to `context`.\n\n/** Under graphql-ws this is `ctx.extra`, created once per socket. */\nexport type WsConnection = object;\n\n// Called per operation, so it must be pure: verifying belongs in `onConnect`.\nexport type WsContextFactory<TContext = unknown> = (\n connectionParams: Record<string, unknown>,\n connection: WsConnection,\n) => Promise<TContext>;\n\n// Admits a connection once, at `ConnectionInit`; `false` closes 4403, retryable.\n\n// It must never throw: an escaping exception closes 4500, which is fatal.\nexport type WsConnectHandler = (\n connectionParams: Record<string, unknown>,\n connection: WsConnection,\n) => Promise<boolean>;\n\n// One object, so no adapter can thread `context` without `onConnect`.\nexport type WsHandlers<TContext = unknown> = {\n onConnect: WsConnectHandler;\n context: WsContextFactory<TContext>;\n};\n\n// Why a WebSocket handshake was refused, carried as the reason on a 4403 close.\n\n// A wire contract. A client reads these to tell an auth refusal -- which no\n// number of retries clears, only a credential change -- from a transient close.\n\n// Both stay 4403: graphql-ws keeps that code retryable, and a reconnect\n// re-evaluates `connectionParams`, so a socket refused before a sign-in does\n// succeed after one. 4401 would kill it before a fresh token could be offered.\n\n// Keep the values stable. A close reason caps at 123 UTF-8 bytes.\n\n/** No authenticated caller resolved, and REQUIRE_AUTHENTICATED_CALLER wants one. */\nexport const WS_CLOSE_REASON_AUTHENTICATION_REQUIRED =\n \"authentication-required\";\n\n/** A bearer was sent and could not be verified. */\nexport const WS_CLOSE_REASON_BEARER_REJECTED = \"bearer-rejected\";\n\n/** Every reason a refusal closes with, for a client matching on the set. */\nexport const WS_AUTH_CLOSE_REASONS = [\n WS_CLOSE_REASON_AUTHENTICATION_REQUIRED,\n WS_CLOSE_REASON_BEARER_REJECTED,\n] as const;\n\nexport type WsDisposer = { dispose: () => void | Promise<void> };\n\n// A Fetch API handler - framework agnostic\nexport type FetchHandler = (request: Request) => Promise<Response>;\n\n/**\n * Handle to a route registered directly on the adapter. Packages hot-reload,\n * so every registration is reversible; disposing a route that is already gone\n * is a no-op.\n *\n * The handle *is* the capability to remove that one route: holding it is the\n * only way to take the route back, and it cannot name any other. An opaque\n * integer would let any holder remove any route by arithmetic, and a caller\n * that disposed twice would eventually free somebody else's registration once\n * ids were reused.\n *\n * Distinct from the `ScopedRouteHandle` a package's HTTP scope hands back,\n * which also carries the public URL the route answers on — at this layer there\n * is no namespace to build one from and no knowledge of the host's origin.\n */\nexport interface AdapterRouteHandle {\n dispose(): void;\n}\n\n/**\n * A framework-agnostic description of one subgraph.\n * Used by IGatewayAdapter.createSupergraphHandler() to compose the supergraph:\n * federation adapters treat it as a service to call over HTTP, while the\n * stitching adapter merges its typeDefs and resolvers in-process.\n */\nexport type SubgraphDefinition = {\n name: string;\n typeDefs: DocumentNode;\n url: string;\n /**\n * The subgraph's resolver map, in-process form. Optional: federation\n * adapters (Apollo, Mercurius) execute subgraphs over HTTP and ignore this,\n * while stitching-style adapters merge these resolvers directly into the\n * supergraph schema. Subgraph authors never see this field - it is filled\n * in by the gateway manager from the subgraph's own resolvers.\n */\n resolvers?: Record<string, unknown>;\n};\n\nexport interface IGatewayAdapter<TContext = unknown> {\n /** One-time startup. */\n start(httpServer: http.Server): Promise<void>;\n\n /**\n * Returns a Fetch API handler for the given schema.\n * Caller (IHttpAdapter) is responsible for mounting it at a path.\n */\n createHandler(\n schema: GraphQLSchema,\n contextFactory: GatewayContextFactory<TContext>,\n ): Promise<FetchHandler>;\n\n /**\n * Create a handler that composes all subgraphs into a supergraph (a\n * federation gateway, or a merged in-process schema under the stitching\n * adapter). getSubgraphs is called eagerly (during setup) and again on every\n * updateSupergraph() call.\n */\n createSupergraphHandler(\n getSubgraphs: () => SubgraphDefinition[],\n httpServer: http.Server,\n contextFactory: GatewayContextFactory<TContext>,\n ): Promise<FetchHandler>;\n\n /**\n * Recompose the supergraph from the current subgraph list and push the update\n * to the running gateway (a federation gateway, or a merged in-process schema\n * under the stitching adapter). No-op if createSupergraphHandler() has not\n * been called yet, or after stop().\n */\n updateSupergraph(): Promise<void>;\n\n // Attach WebSocket subscriptions. Both halves of `handlers` must be passed on.\n\n /** Without `onConnect`, refusing would mean throwing: an unretryable 4500. */\n attachWebSocket(\n wsServer: WebSocketServer,\n schema: GraphQLSchema,\n handlers: WsHandlers<TContext>,\n ): WsDisposer;\n\n stop(): Promise<void>;\n}\n\n/**\n * Methods a node route may bind. OPTIONS is excluded: the framework's CORS\n * plugin owns preflight, and a duplicate registration conflicts at startup.\n */\nexport type HttpMethod = \"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\";\n\nexport interface NodeRouteOptions {\n /** Serve sub-paths too, not just an exact path match. */\n prefix?: boolean;\n\n /**\n * Deliver the request body as the client sent it: unparsed and byte-exact.\n * The handler reads `req` itself; the `body` argument stays undefined.\n *\n * Without this, the body has already been parsed by the time the handler\n * runs, so a signature computed over the raw payload cannot be verified —\n * re-encoding loses key order, whitespace and duplicate keys. This is the\n * one capability a webhook endpoint cannot do without, and the reason a\n * route needs to be dispatched ahead of the body parsers rather than behind\n * them.\n */\n rawBody?: boolean;\n}\n\nexport interface IHttpAdapter {\n /** Set up CORS and body-parser equivalent middleware. */\n setupMiddleware(config: {\n corsOptions?: CorsOptions;\n bodyLimit?: string;\n }): void;\n\n /**\n * Mount a Fetch API handler. Returns a handle whose `dispose()` removes it.\n * - exact = false (default): exact path match.\n * - exact = true: prefix match - handler also receives all sub-paths.\n *\n * Mounting a path that already holds a fetch mount of the same kind\n * replaces the previous one (last write wins).\n */\n mount(\n path: string,\n handler: FetchHandler,\n options?: {\n prefix?: boolean;\n /** @deprecated Misleading name: this always meant *prefix*, not exact. */\n exact?: boolean;\n },\n ): AdapterRouteHandle;\n\n /**\n * Register a GET-only route that returns a Fetch Response (for health,\n * explorer, etc.). Returns a handle whose `dispose()` removes it.\n */\n getRoute(\n path: string,\n handler: (request: Request) => Response | Promise<Response>,\n ): AdapterRouteHandle;\n\n /**\n * Start listening on the given port. Returns the underlying http.Server\n * so callers can attach WebSocket servers. Without `host` it binds the\n * wildcard address.\n */\n listen(port: number, tls?: TlsOptions, host?: string): Promise<http.Server>;\n\n /**\n * Mount a raw Connect/Express-compatible middleware function (e.g. Vite dev\n * server middleware). The implementation is adapter-specific; for Express this\n * is equivalent to `app.use(middleware)`.\n */\n mountRawMiddleware(middleware: unknown): void;\n\n /**\n * Register a method-specific route handler using Node.js core HTTP types.\n * Use this when a Fetch API FetchHandler is not possible (e.g. streaming\n * protocols that require direct access to IncomingMessage/ServerResponse).\n *\n * The req/res objects are `http.IncomingMessage`/`http.ServerResponse`\n * (Express Request/Response are compatible subtypes). Returns a handle\n * whose `dispose()` removes it.\n */\n mountNodeRoute(\n method: HttpMethod,\n path: string,\n // Node route handlers may be synchronous or async; the adapter does not\n // await them, and answers a throw or rejection with a 500.\n handler: (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body?: unknown,\n ) => void | Promise<void>,\n options?: NodeRouteOptions,\n ): AdapterRouteHandle;\n\n /**\n * Register framework-specific Sentry error-capturing middleware after all routes\n * are mounted. Each adapter calls the Sentry setup function appropriate for its\n * framework (e.g. setupExpressErrorHandler, setupFastifyErrorHandler).\n * No-op if Sentry is not relevant for the adapter.\n */\n setupSentryErrorHandler(sentry: object): void;\n\n /** The raw framework handle (e.g. Express app). Cast as needed at call sites. */\n readonly handle: unknown;\n}\n","import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/**\n * A package's namespace is its npm name, used verbatim as one or two path\n * segments. Nothing is slugged: dropping the scope, folding `.`/`_` to `-` or\n * lower-casing would all map distinct package names onto one namespace, and a\n * lossy mapping means two packages can silently claim the same URL space.\n * Verbatim is injective, so there is no collision left to detect.\n */\n\n/**\n * npm's package-name grammar, per segment. Deliberately the same shape the HTTP\n * package loader validates with, so a name that can be installed can be routed.\n */\nconst SEGMENT = /^[a-z0-9][-a-z0-9._]*$/i;\n\n/** Segments that would read as path traversal rather than as a name. */\nconst TRAVERSAL = new Set([\".\", \"..\"]);\n\nexport class InvalidNamespaceError extends Error {}\n\n/**\n * Turns a package name into the path segments it occupies.\n * `@powerhousedao/workflow` → [\"@powerhousedao\", \"workflow\"]\n * `document-model` → [\"document-model\"]\n */\nexport function namespaceSegments(packageName: string): string[] {\n if (!packageName) {\n throw new InvalidNamespaceError(\"Package name is empty\");\n }\n\n const scoped = packageName.startsWith(\"@\");\n const parts = (scoped ? packageName.slice(1) : packageName).split(\"/\");\n\n if (parts.length !== (scoped ? 2 : 1)) {\n throw new InvalidNamespaceError(\n `\"${packageName}\" is not a package name: expected ${\n scoped ? \"@scope/name\" : \"name\"\n }`,\n );\n }\n\n for (const part of parts) {\n if (TRAVERSAL.has(part) || !SEGMENT.test(part)) {\n throw new InvalidNamespaceError(\n `\"${packageName}\" contains a segment that is not a valid npm name part: \"${part}\"`,\n );\n }\n }\n\n return scoped ? [`@${parts[0]!}`, parts[1]!] : parts;\n}\n\n/**\n * The path a package's routes hang off, relative to the package prefix.\n * Scoped names occupy two segments — the addressing unpkg and jsdelivr use.\n */\nexport function namespacePath(packageName: string): string {\n return namespaceSegments(packageName).join(\"/\");\n}\n\n/**\n * The same path with the leading `@` percent-encoded. Both routers match the\n * raw pathname, so a client that percent-encodes each segment would otherwise\n * 404. Registering both spellings avoids decoding the pathname before matching,\n * which would turn `%2f` into `/` and let a crafted URL cross segment\n * boundaries. `%40` cannot introduce a boundary, which is what makes this safe.\n */\nexport function encodedNamespacePath(packageName: string): string | undefined {\n const path = namespacePath(packageName);\n return path.startsWith(\"@\") ? `%40${path.slice(1)}` : undefined;\n}\n\n/**\n * A route path a package supplied. Must be relative and must not climb out of\n * the scope.\n */\nexport function assertRelativeRoutePath(path: string): string {\n if (path.startsWith(\"/\")) {\n throw new InvalidNamespaceError(\n `Route path \"${path}\" must be relative to the scope, not absolute`,\n );\n }\n if (/^[a-z][a-z0-9+.-]*:/i.test(path)) {\n throw new InvalidNamespaceError(\n `Route path \"${path}\" must be a path, not a URL`,\n );\n }\n if (path.split(\"/\").some((segment) => TRAVERSAL.has(segment))) {\n throw new InvalidNamespaceError(\n `Route path \"${path}\" must not contain \".\" or \"..\" segments`,\n );\n }\n return path.replace(/^\\/+|\\/+$/g, \"\");\n}\n\n/**\n * Resolves the npm name a package is routed under from the key the package\n * manager holds it by. That key is the specifier as configured, which is not\n * always a name:\n * - `@scope/pkg` — already a name.\n * - `@scope/pkg@1.3.9` — a registry spec; only the loader strips the tag.\n * - `/Users/me/project` — the local project, which switchboard registers by\n * `process.cwd()`. Its real name lives in its package.json.\n *\n * Deriving a URL segment straight from the key would give a developer's home\n * directory a route namespace, so the path form is resolved rather than slugged.\n */\nexport function resolvePackageName(\n key: string,\n readPackageJsonName: (dir: string) => string | undefined = defaultReadName,\n): string {\n const withoutVersion = stripVersionSpec(key);\n if (isPackageName(withoutVersion)) return withoutVersion;\n\n if (key.startsWith(\"/\") || key.startsWith(\".\")) {\n const name = readPackageJsonName(key);\n if (name && isPackageName(name)) return name;\n throw new InvalidNamespaceError(\n `Package at \"${key}\" has no usable name in its package.json, so it cannot host routes`,\n );\n }\n\n throw new InvalidNamespaceError(\n `\"${key}\" is not a package name and not a path, so it cannot host routes`,\n );\n}\n\nfunction isPackageName(value: string): boolean {\n try {\n namespaceSegments(value);\n return true;\n } catch {\n return false;\n }\n}\n\n/** `@scope/pkg@1.3.9` → `@scope/pkg`; `pkg@1.0.0` → `pkg`. */\nfunction stripVersionSpec(key: string): string {\n const at = key.lastIndexOf(\"@\");\n if (at <= 0) return key;\n return key.slice(0, at);\n}\n\nfunction defaultReadName(dir: string): string | undefined {\n try {\n // Deliberately synchronous and best-effort: this runs once per package at\n // load, and a missing or unreadable manifest is a normal outcome.\n const raw = readFileSync(join(dir, \"package.json\"), \"utf8\");\n const parsed = JSON.parse(raw) as { name?: unknown };\n return typeof parsed.name === \"string\" ? parsed.name : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * A mount path the host named for one of its own route groups.\n *\n * The host owns the whole URL space — it holds the adapter — so unlike a\n * package it may name an absolute path. That is the difference between hosting\n * and being hosted, and it is why this lives on the service rather than on a\n * scope: a package is only ever handed a scope, and a scope has no way to\n * express a path outside itself.\n *\n * What the host still may not name is anything that is not one stable literal\n * prefix. A traversal segment, or a pattern segment, would make the group's own\n * routes unpredictable relative to each other. Returns the normalized path,\n * with a leading and no trailing slash.\n */\nexport function assertHostMountPath(path: string): string {\n if (!path.startsWith(\"/\")) {\n throw new InvalidNamespaceError(\n `Host mount path \"${path}\" must be absolute, e.g. \"/webhooks\"`,\n );\n }\n\n const segments = path.split(\"/\").filter((segment) => segment.length > 0);\n if (segments.length === 0) {\n throw new InvalidNamespaceError(\n `Host mount path \"${path}\" is the whole URL space, which is the adapter rather than a scope of it`,\n );\n }\n\n for (const segment of segments) {\n if (TRAVERSAL.has(segment)) {\n throw new InvalidNamespaceError(\n `Host mount path \"${path}\" must not contain \".\" or \"..\" segments`,\n );\n }\n if (segment.startsWith(\":\") || segment.includes(\"*\")) {\n throw new InvalidNamespaceError(\n `Host mount path \"${path}\" must be a literal prefix, not a pattern: \"${segment}\"`,\n );\n }\n }\n\n return `/${segments.join(\"/\")}`;\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport type { RouteTransport } from \"./types.js\";\n\n/** Converts Node incoming headers to Fetch Headers. */\nexport function fetchHeaders(req: IncomingMessage): Headers {\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (value === undefined) continue;\n headers.set(key, Array.isArray(value) ? value.join(\", \") : value);\n }\n return headers;\n}\n\n/**\n * Where the request reached the host. `trustProxy` says whether the\n * `x-forwarded-*` headers may be believed: they are client-written, so with no\n * proxy in front a caller could pick the origin a route advertises. The `host`\n * header is always read, being the request's own target.\n */\nexport function resolveTransport(\n req: IncomingMessage,\n trustProxy = false,\n): RouteTransport {\n const header = (name: string): string | undefined => {\n const value = req.headers[name];\n const first = Array.isArray(value) ? value[0] : value;\n return first?.split(\",\")[0]?.trim() || undefined;\n };\n const forwarded = (name: string): string | undefined =>\n trustProxy ? header(name) : undefined;\n\n const encrypted = (req.socket as { encrypted?: boolean }).encrypted === true;\n const proto =\n forwarded(\"x-forwarded-proto\") ?? (encrypted ? \"https\" : \"http\");\n const host = forwarded(\"x-forwarded-host\") ?? header(\"host\") ?? \"localhost\";\n const prefix = forwarded(\"x-forwarded-prefix\") ?? \"\";\n\n return { proto, host, prefix, baseUrl: `${proto}://${host}${prefix}` };\n}\n\nexport class BodyTooLargeError extends Error {}\n\n/**\n * Buffers the request body, refusing anything past `maxBytes`.\n *\n * Written with events rather than `for await`, because an async iterator\n * destroys the stream when the loop exits early — which tears down the socket\n * before a 413 can be written to it. The stream is left paused instead, so the\n * caller can answer and then close the connection deliberately.\n */\nexport function readBody(\n req: IncomingMessage,\n maxBytes: number,\n): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n let settled = false;\n\n const settle = (error?: Error): void => {\n if (settled) return;\n settled = true;\n req.off(\"data\", onData);\n req.off(\"end\", onEnd);\n req.off(\"error\", onError);\n req.pause();\n if (error) reject(error);\n else resolve(Buffer.concat(chunks));\n };\n\n const onData = (chunk: Buffer): void => {\n size += chunk.length;\n if (size > maxBytes) {\n settle(new BodyTooLargeError(`Body exceeds ${maxBytes} bytes`));\n return;\n }\n chunks.push(chunk);\n };\n const onEnd = (): void => settle();\n const onError = (error: Error): void => settle(error);\n\n req.on(\"data\", onData);\n req.once(\"end\", onEnd);\n req.once(\"error\", onError);\n });\n}\n\n/**\n * Copies a Fetch Response onto a Node response, streaming the body. A HEAD\n * response carries headers only, however the handler filled the body.\n */\nexport async function writeResponse(\n res: ServerResponse,\n response: Response,\n method: string,\n): Promise<void> {\n if (res.writableEnded || res.headersSent) return;\n\n res.statusCode = response.status;\n response.headers.forEach((value, key) => {\n res.setHeader(key, value);\n });\n\n if (!response.body || method.toUpperCase() === \"HEAD\") {\n res.end();\n return;\n }\n\n const source = Readable.fromWeb(response.body as never);\n res.on(\"close\", () => source.destroy());\n await pipeline(source, res);\n}\n\n/** Answers with a JSON error, unless the response is already underway. */\nexport function writeError(\n res: ServerResponse,\n status: number,\n message: string,\n): void {\n if (res.writableEnded || res.headersSent) {\n res.destroy();\n return;\n }\n const body = JSON.stringify({ error: message });\n res.statusCode = status;\n res.setHeader(\"content-type\", \"application/json\");\n res.setHeader(\"content-length\", Buffer.byteLength(body));\n res.end(body);\n}\n","import { childLogger } from \"document-model\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport posix from \"node:path/posix\";\nimport { Readable } from \"node:stream\";\nimport type {\n AdapterRouteHandle as AdapterHandle,\n IHttpAdapter,\n} from \"../graphql/gateway/types.js\";\nimport type { AuthService } from \"../services/auth.service.js\";\nimport type { WebhookService } from \"./webhook-service.js\";\nimport {\n assertHostMountPath,\n assertRelativeRoutePath,\n encodedNamespacePath,\n InvalidNamespaceError,\n namespacePath,\n resolvePackageName,\n} from \"./namespace.js\";\nimport {\n BodyTooLargeError,\n fetchHeaders,\n readBody,\n resolveTransport,\n writeError,\n writeResponse,\n} from \"./node-response.js\";\nimport type {\n IHttpScope,\n IWebhookScope,\n NodeRouteSpec,\n RouteActor,\n RouteAuth,\n RouteContext,\n ScopedRouteHandle,\n RouteHandler,\n RouteMethod,\n RouteOptions,\n RouteSpec,\n} from \"./types.js\";\n\nconst logger = childLogger([\"reactor-api\", \"http-routes\"]);\n\n/** The segment package routes live under, inside the host's base path. */\nexport const PACKAGE_ROUTE_SEGMENT = \"api\";\n\n/** The namespace core's own subgraphs and services register under. */\nexport const CORE_PACKAGE_NAME = \"@powerhousedao/reactor-api\";\n\n/** Generous enough for any request a route should be buffering at all. */\nconst DEFAULT_MAX_BODY_BYTES = 1_048_576;\n\nconst ANONYMOUS: RouteActor = { user: undefined, authEnabled: false };\n\nexport interface HttpRouteServiceOptions {\n httpAdapter: IHttpAdapter;\n /** Absent on a host with no webhook store; `scope.webhooks` then refuses. */\n webhooks?: WebhookService;\n /** The host's base path, i.e. config.basePath. */\n basePath?: string;\n /** Absent when auth is disabled host-wide; every route then sees an anonymous actor. */\n authService?: AuthService;\n /** The host's public origin; empty when unknowable, the only case where advertised URLs degrade to paths. */\n publicUrl?: string;\n /** Whether to believe the `X-Forwarded-*` headers that name the request's public origin.\n * Off by default: they are client-written, so with no proxy in front a caller could choose the origin a route advertises. */\n trustProxy?: boolean;\n}\n\ntype Registration = { path: string; handles: AdapterHandle[] };\n\n/** Owns the URL space packages serve from, handing each a scope bound to its own namespace. The prefix nests inside\n * the host's base path (`<basePath>/api`), so core collisions are prevented by URL shape, not a reserved-name list. */\nexport class HttpRouteService {\n readonly #adapter: IHttpAdapter;\n readonly #authService: AuthService | undefined;\n readonly #prefix: string;\n readonly #publicUrl: string;\n readonly #trustProxy: boolean;\n readonly #scopes = new Map<string, HttpScope>();\n\n readonly #webhooks: WebhookService | undefined;\n\n constructor({\n httpAdapter,\n basePath = \"/\",\n authService,\n webhooks,\n publicUrl = \"\",\n trustProxy = false,\n }: HttpRouteServiceOptions) {\n this.#adapter = httpAdapter;\n this.#authService = authService;\n this.#webhooks = webhooks;\n this.#publicUrl = publicUrl.replace(/\\/+$/, \"\");\n this.#trustProxy = trustProxy;\n this.#prefix = posix.join(\"/\", basePath, PACKAGE_ROUTE_SEGMENT);\n }\n\n /** The absolute path packages are mounted under. */\n get prefix(): string {\n return this.#prefix;\n }\n\n /** The scope for a package; idempotent per name, so a reload cannot accumulate namespaces. Throws when two packages\n * resolve to one namespace — with verbatim names that means one package configured twice, a genuine ambiguity. */\n scopeFor(packageKey: string): IHttpScope {\n const packageName = resolvePackageName(packageKey);\n const namespace = namespacePath(packageName);\n const encoded = encodedNamespacePath(packageName);\n return this.#scope({\n owner: packageName,\n base: posix.join(this.#prefix, namespace),\n encodedBase: encoded ? posix.join(this.#prefix, encoded) : undefined,\n claim: `the route namespace \"${namespace}\"`,\n webhooks: this.#webhooks?.scopeFor(packageName),\n onDispose: () => this.#webhooks?.disposeScope(packageName),\n });\n }\n\n /** A scope at a host-named path; on the service, not `IHttpScope`, so a package can never name one. Namespacing is package\n * policy: the host owns its URL space and third parties hold its URLs, so the path is verbatim and outside the package prefix. */\n hostScope(name: string, mountPath: string): IHttpScope {\n const base = assertHostMountPath(mountPath);\n if (base === this.#prefix || base.startsWith(`${this.#prefix}/`)) {\n throw new InvalidNamespaceError(\n `Host scope \"${name}\" cannot mount at \"${base}\": that is the package route prefix, which packages own`,\n );\n }\n return this.#scope({\n owner: name,\n base,\n encodedBase: undefined,\n claim: `the mount path \"${base}\"`,\n // None of its own: a token-addressed endpoint belongs to whoever minted the token, always a package.\n webhooks: undefined,\n onDispose: () => undefined,\n });\n }\n\n /** Idempotent per base path, so a package reload cannot accumulate namespaces. Two owners wanting one path is an error —\n * with verbatim names that needs one package configured twice at different versions, a genuine ambiguity, not a clash. */\n #scope(options: {\n owner: string;\n base: string;\n encodedBase: string | undefined;\n claim: string;\n webhooks: IWebhookScope | undefined;\n onDispose: () => void;\n }): IHttpScope {\n const { owner, base } = options;\n const existing = this.#scopes.get(base);\n if (existing) {\n if (existing.owner !== owner) {\n throw new Error(\n `\"${owner}\" wants ${options.claim}, which \"${existing.owner}\" already holds`,\n );\n }\n return existing;\n }\n\n const scope = new HttpScope({\n owner,\n base,\n encodedBase: options.encodedBase,\n publicUrl: this.#publicUrl,\n trustProxy: this.#trustProxy,\n adapter: this.#adapter,\n authService: this.#authService,\n webhooks: options.webhooks,\n onDispose: () => {\n this.#scopes.delete(base);\n options.onDispose();\n },\n });\n this.#scopes.set(base, scope);\n return scope;\n }\n\n /** Like {@link scopeFor}, but never throws: a key resolving to no usable npm name gets a scope that refuses\n * registrations, so one unroutable package cannot stop the host booting — it fails only if it serves a route. */\n scopeForOrNull(packageKey: string): IHttpScope {\n try {\n return this.scopeFor(packageKey);\n } catch (error) {\n if (!(error instanceof InvalidNamespaceError)) throw error;\n // Scoped package names carry a leading `@`, which the logger reads as\n // a replacement token: pass them positionally so the name survives.\n logger.warn(\n 'Package \"@package\" cannot host HTTP routes: @reason',\n packageKey,\n error.message,\n );\n return new UnroutableScope(packageKey, error.message);\n }\n }\n\n /** Releases a package's routes, e.g. when it is replaced or removed. */\n disposeScope(packageKey: string): void {\n try {\n const namespace = namespacePath(resolvePackageName(packageKey));\n this.#scopes.get(posix.join(this.#prefix, namespace))?.dispose();\n } catch (error) {\n if (!(error instanceof InvalidNamespaceError)) throw error;\n }\n }\n\n disposeAll(): void {\n for (const scope of [...this.#scopes.values()]) scope.dispose();\n }\n}\n\ninterface HttpScopeOptions {\n /** A package's npm name, or the host's name for one of its route groups. */\n owner: string;\n /** Absolute path every route in the scope hangs off. */\n base: string;\n /** The same base with a scoped name's `@` percent-encoded, when it has one. */\n encodedBase: string | undefined;\n publicUrl: string;\n trustProxy: boolean;\n adapter: IHttpAdapter;\n authService: AuthService | undefined;\n webhooks: IWebhookScope | undefined;\n onDispose: () => void;\n}\n\nclass HttpScope implements IHttpScope {\n readonly owner: string;\n readonly #base: string;\n readonly #publicUrl: string;\n readonly #trustProxy: boolean;\n readonly #encodedBase: string | undefined;\n readonly #adapter: IHttpAdapter;\n readonly #authService: AuthService | undefined;\n readonly #onDispose: () => void;\n readonly #registrations = new Map<string, Registration>();\n readonly #webhooks: IWebhookScope;\n\n constructor(options: HttpScopeOptions) {\n this.owner = options.owner;\n this.#base = options.base;\n this.#publicUrl = options.publicUrl;\n this.#trustProxy = options.trustProxy;\n this.#encodedBase = options.encodedBase;\n this.#adapter = options.adapter;\n this.#authService = options.authService;\n this.#onDispose = options.onDispose;\n this.#webhooks = options.webhooks ?? unavailableWebhooks(options.owner);\n }\n\n get baseUrl(): string {\n return `${this.#publicUrl}${this.#base}`;\n }\n\n get webhooks(): IWebhookScope {\n return this.#webhooks;\n }\n\n get(path: string, a: RouteOptions | RouteHandler, b?: RouteHandler) {\n return this.#shorthand(\"GET\", path, a, b);\n }\n post(path: string, a: RouteOptions | RouteHandler, b?: RouteHandler) {\n return this.#shorthand(\"POST\", path, a, b);\n }\n put(path: string, a: RouteOptions | RouteHandler, b?: RouteHandler) {\n return this.#shorthand(\"PUT\", path, a, b);\n }\n patch(path: string, a: RouteOptions | RouteHandler, b?: RouteHandler) {\n return this.#shorthand(\"PATCH\", path, a, b);\n }\n delete(path: string, a: RouteOptions | RouteHandler, b?: RouteHandler) {\n return this.#shorthand(\"DELETE\", path, a, b);\n }\n head(path: string, a: RouteOptions | RouteHandler, b?: RouteHandler) {\n return this.#shorthand(\"HEAD\", path, a, b);\n }\n\n #shorthand(\n method: RouteMethod,\n path: string,\n a: RouteOptions | RouteHandler,\n b?: RouteHandler,\n ): ScopedRouteHandle {\n const options = typeof a === \"function\" ? {} : a;\n const handler = typeof a === \"function\" ? a : b;\n if (!handler) {\n throw new Error(`Route ${method} ${path} was registered with no handler`);\n }\n return this.route({ ...options, method, path, handler });\n }\n\n route(spec: RouteSpec): ScopedRouteHandle {\n const body = spec.body ?? \"parsed\";\n return this.#register(spec, (req, res, ctx) =>\n this.#serve(spec, body, req, res, ctx),\n );\n }\n\n nodeRoute(spec: NodeRouteSpec): ScopedRouteHandle {\n return this.#register(spec, (req, res, ctx) => spec.handler(req, res, ctx));\n }\n\n dispose(): void {\n for (const registration of this.#registrations.values()) {\n for (const handle of registration.handles) handle.dispose();\n }\n this.#registrations.clear();\n this.#onDispose();\n }\n\n /** Mounts one route under this scope's namespace, in both the verbatim and the\n * percent-encoded spelling of a scoped name. */\n #register(\n spec: {\n method: RouteMethod | RouteMethod[];\n path: string;\n auth?: RouteAuth;\n maxBodyBytes?: number;\n prefix?: boolean;\n },\n run: (\n req: IncomingMessage,\n res: ServerResponse,\n ctx: Omit<RouteContext, \"rawBody\" | \"signal\">,\n ) => void | Promise<void>,\n ): ScopedRouteHandle {\n const relative = assertRelativeRoutePath(spec.path);\n const methods = Array.isArray(spec.method) ? spec.method : [spec.method];\n const routePath = relative ? posix.join(this.#base, relative) : this.#base;\n\n const key = `${methods.join(\",\")} ${routePath}`;\n if (this.#registrations.has(key)) {\n // Silent shadowing is how a route disappears without anyone noticing;\n // for a security-relevant surface that has to be loud.\n throw new Error(`Route ${key} is already registered by \"${this.owner}\"`);\n }\n\n const handles: AdapterHandle[] = [];\n const paths = [routePath];\n if (this.#encodedBase) {\n paths.push(\n relative ? posix.join(this.#encodedBase, relative) : this.#encodedBase,\n );\n }\n\n for (const path of paths) {\n for (const method of methods) {\n handles.push(\n this.#adapter.mountNodeRoute(\n method,\n path,\n (req, res) => {\n void this.#guard(spec, req, res, run);\n },\n // The service owns body handling for every route it registers, so\n // it always takes the unparsed stream from the adapter.\n { rawBody: true, prefix: spec.prefix },\n ),\n );\n }\n }\n\n this.#registrations.set(key, { path: routePath, handles });\n logger.debug(\"Registered @route for @package\", key, this.owner);\n\n return {\n url: `${this.#publicUrl}${routePath}`,\n dispose: () => {\n const registration = this.#registrations.get(key);\n if (!registration) return;\n for (const handle of registration.handles) handle.dispose();\n this.#registrations.delete(key);\n },\n };\n }\n\n /** Authenticate, then run. */\n async #guard(\n spec: { auth?: RouteAuth },\n req: IncomingMessage,\n res: ServerResponse,\n run: (\n req: IncomingMessage,\n res: ServerResponse,\n ctx: Omit<RouteContext, \"rawBody\" | \"signal\">,\n ) => void | Promise<void>,\n ): Promise<void> {\n try {\n const actor = await this.#authenticate(spec.auth ?? \"renown\", req, res);\n if (actor === REJECTED) return;\n\n await run(req, res, {\n params: routeParams(req),\n user: actor?.user,\n authEnabled: actor?.authEnabled ?? false,\n transport: resolveTransport(req, this.#trustProxy),\n });\n } catch (error) {\n logger.error(\n \"Route handler failed for @package\",\n this.owner,\n error as Error,\n );\n writeError(res, 500, \"Internal server error\");\n }\n }\n\n /** Resolves the caller, answering the request itself when the route refuses it;\n * returns REJECTED in that case so the caller stops. */\n async #authenticate(\n auth: RouteAuth,\n req: IncomingMessage,\n res: ServerResponse,\n ): Promise<RouteActor | undefined | typeof REJECTED> {\n if (auth === \"public\") return undefined;\n\n if (typeof auth === \"function\") {\n const result = await auth(req);\n if (!result.authorized) {\n if (\"response\" in result) {\n await writeResponse(res, result.response, req.method ?? \"GET\");\n } else {\n writeError(res, result.status, result.message);\n }\n return REJECTED;\n }\n return undefined;\n }\n\n // No auth service means auth is disabled host-wide: every caller is the\n // anonymous actor, which is the only way to opt out of bearer checking.\n if (!this.#authService) return ANONYMOUS;\n\n const result = await this.#authService.verifyBearer(\n req.headers.authorization,\n );\n\n if (result instanceof Response) {\n await writeResponse(res, result, req.method ?? \"GET\");\n return REJECTED;\n }\n\n if (result.auth_enabled && !result.user && auth === \"renown\") {\n writeError(res, 401, \"Authentication required\");\n return REJECTED;\n }\n\n return { user: result.user, authEnabled: result.auth_enabled };\n }\n\n /** Builds the Fetch Request from the raw stream and runs the handler. */\n async #serve(\n spec: RouteSpec,\n body: NonNullable<RouteSpec[\"body\"]>,\n req: IncomingMessage,\n res: ServerResponse,\n ctx: Omit<RouteContext, \"rawBody\" | \"signal\">,\n ): Promise<void> {\n const method = req.method ?? \"GET\";\n const url = `${ctx.transport.baseUrl}${req.url ?? \"/\"}`;\n\n const controller = new AbortController();\n req.once(\"close\", () => controller.abort());\n\n let raw: Buffer | undefined;\n let init: RequestInit & { duplex?: \"half\" } = {\n method,\n headers: fetchHeaders(req),\n signal: controller.signal,\n };\n\n const carriesBody = method !== \"GET\" && method !== \"HEAD\";\n if (carriesBody && body !== \"none\") {\n if (body === \"stream\") {\n init = {\n ...init,\n body: Readable.toWeb(req) as ReadableStream,\n duplex: \"half\",\n };\n } else {\n try {\n raw = await readBody(\n req,\n spec.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES,\n );\n } catch (error) {\n if (error instanceof BodyTooLargeError) {\n // The rest of the body is never read, so the connection cannot be\n // reused: leftover bytes would be parsed as the next request.\n res.setHeader(\"connection\", \"close\");\n res.once(\"finish\", () => req.destroy());\n writeError(res, 413, \"Payload too large\");\n return;\n }\n throw error;\n }\n // Verbatim bytes, so a handler verifying a signature over the payload sees what the client sent.\n // A view, not a copy: an upload can be large.\n /* The narrowing is for TypeScript: `BufferSource` excludes a SharedArrayBuffer-backed view while Buffer's\n * `.buffer` is the wider `ArrayBufferLike`; Node never pools a Buffer on shared memory, so it is sound. */\n if (raw.length)\n init = {\n ...init,\n body: new Uint8Array(\n raw.buffer as ArrayBuffer,\n raw.byteOffset,\n raw.byteLength,\n ),\n };\n }\n }\n\n const response = await spec.handler(new Request(url, init), {\n ...ctx,\n rawBody: body === \"raw\" ? (raw ?? Buffer.alloc(0)) : undefined,\n signal: controller.signal,\n });\n\n await writeResponse(res, response, method);\n }\n}\n\nconst REJECTED = Symbol(\"rejected\");\n\nfunction routeParams(req: IncomingMessage): Record<string, string> {\n const params = (req as IncomingMessage & { params?: unknown }).params;\n if (!params || typeof params !== \"object\") return {};\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(params)) {\n if (typeof value === \"string\") out[key] = value;\n else if (Array.isArray(value)) out[key] = value.join(\"/\");\n }\n return out;\n}\n\n/** Stands in for a package that cannot be routed — its key resolves to no npm name. Registering a route throws with\n * the reason; nothing else does, so the package still loads and its non-HTTP behaviour is unaffected. */\nclass UnroutableScope implements IHttpScope {\n readonly owner: string;\n readonly baseUrl = \"\";\n readonly #reason: string;\n\n constructor(packageKey: string, reason: string) {\n this.owner = packageKey;\n this.#reason = reason;\n }\n\n #refuse(): never {\n throw new Error(\n `Package \"${this.owner}\" cannot host HTTP routes: ${this.#reason}`,\n );\n }\n\n get(): never {\n this.#refuse();\n }\n post(): never {\n this.#refuse();\n }\n put(): never {\n this.#refuse();\n }\n patch(): never {\n this.#refuse();\n }\n delete(): never {\n this.#refuse();\n }\n head(): never {\n this.#refuse();\n }\n route(): never {\n this.#refuse();\n }\n nodeRoute(): never {\n this.#refuse();\n }\n get webhooks(): IWebhookScope {\n return unavailableWebhooks(this.owner);\n }\n dispose(): void {\n // Nothing was ever registered.\n }\n}\n\n/** Stands in when the host has no webhook store configured. */\nfunction unavailableWebhooks(packageName: string): IWebhookScope {\n return {\n // No endpoints exist to advertise, so the question does not arise.\n hasPublicOrigin: false,\n register: () =>\n Promise.reject(\n new Error(\n `Webhooks are not available on this host, so \"${packageName}\" cannot register one`,\n ),\n ),\n };\n}\n","/** Signature verification for inbound webhooks, over the raw bytes: a parse/re-encode\n * round trip changes key order, whitespace and duplicate keys, so every scheme here needs the exact octets the provider sent. */\nimport { createHmac, timingSafeEqual, type BinaryLike } from \"node:crypto\";\n\nimport type {\n WebhookHashAlgorithm,\n WebhookScheme,\n WebhookSignatureEncoding,\n WebhookVerification,\n} from \"@powerhousedao/shared/processors\";\n\nexport type {\n WebhookHashAlgorithm,\n WebhookScheme,\n WebhookSignatureEncoding,\n WebhookVerification,\n};\n\nexport const DEFAULT_TOLERANCE_SECONDS = 300;\n\n/** Header each scheme reads when the caller does not name one: the name the format is\n * most often carried in, not a property of it, so `WebhookVerification.header` overrides any of them. */\nexport const DEFAULT_SCHEME_HEADER: Record<WebhookScheme, string> = {\n none: \"\",\n token: \"x-webhook-token\",\n hmac: \"x-signature\",\n \"hmac-prefixed\": \"x-hub-signature-256\",\n \"hmac-timestamped\": \"stripe-signature\",\n};\n\nexport type VerifyResult = { ok: true } | { ok: false; reason: string };\n\nconst OK: VerifyResult = { ok: true };\n\n/** Constant-time over equal-length inputs; a length mismatch is already a rejection, so\n * the early return leaks nothing a caller could not measure. */\nfunction secureEquals(a: string, b: string): boolean {\n const left = Buffer.from(a, \"utf8\");\n const right = Buffer.from(b, \"utf8\");\n if (left.length !== right.length) return false;\n return timingSafeEqual(left, right);\n}\n\nfunction hmacDigest(\n secret: string,\n payload: BinaryLike,\n verification: WebhookVerification,\n): string {\n return createHmac(verification.algorithm ?? \"sha256\", secret)\n .update(payload)\n .digest(verification.encoding ?? \"hex\");\n}\n\n/** Hex folds case, so an uppercased digest still verifies. Base64 must not: two distinct\n * digests can differ only in case, so folding there would accept a signature that is not the one computed. */\nfunction digestEquals(\n presented: string,\n expected: string,\n verification: WebhookVerification,\n): boolean {\n const candidate = presented.trim();\n if ((verification.encoding ?? \"hex\") === \"base64\") {\n return secureEquals(candidate, expected);\n }\n return secureEquals(candidate.toLowerCase(), expected.toLowerCase());\n}\n\n/** The label `hmac-prefixed` expects before the digest. */\nfunction signaturePrefix(verification: WebhookVerification): string {\n return verification.prefix ?? `${verification.algorithm ?? \"sha256\"}=`;\n}\n\n/** `t=<unix>,v1=<hex>[,v1=<hex>…]`. Several `v1` values appear while a secret is being\n * rotated, and any one of them matching is a pass. */\nfunction parseTimestampedHeader(value: string): {\n timestamp?: number;\n signatures: string[];\n} {\n const signatures: string[] = [];\n let timestamp: number | undefined;\n for (const part of value.split(\",\")) {\n const separator = part.indexOf(\"=\");\n if (separator < 0) continue;\n const key = part.slice(0, separator).trim();\n const item = part.slice(separator + 1).trim();\n if (key === \"t\") timestamp = Number(item);\n // Not lower-cased here: the encoding decides whether case matters, and\n // digestEquals is where that is known.\n else if (key === \"v1\") signatures.push(item);\n }\n return { timestamp, signatures };\n}\n\nexport function schemeHeader(verification: WebhookVerification): string {\n return (\n verification.header ?? DEFAULT_SCHEME_HEADER[verification.scheme]\n ).toLowerCase();\n}\n\n/** Verifies a delivery against the configured scheme; `raw` must be the exact bytes\n * received. The reason is for the log only: callers answer a fixed 401, so a probing sender learns nothing from the body. */\nexport function verifyWebhook(options: {\n verification: WebhookVerification;\n headers: Record<string, string>;\n raw: Buffer;\n now?: Date;\n}): VerifyResult {\n const { verification, headers, raw } = options;\n if (verification.scheme === \"none\") return OK;\n if (!verification.secret) {\n return { ok: false, reason: \"signing secret missing\" };\n }\n\n const header = schemeHeader(verification);\n // Absent and empty are one case: the index type hides the former.\n const presented: string | undefined = headers[header];\n if (!presented) return { ok: false, reason: `header \"${header}\" absent` };\n\n const secret = verification.secret;\n const tolerance = verification.toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;\n\n switch (verification.scheme) {\n case \"token\":\n return secureEquals(presented, secret)\n ? OK\n : { ok: false, reason: \"token mismatch\" };\n case \"hmac\":\n return digestEquals(\n presented,\n hmacDigest(secret, raw, verification),\n verification,\n )\n ? OK\n : { ok: false, reason: \"hmac mismatch\" };\n case \"hmac-prefixed\": {\n const expected = `${signaturePrefix(verification)}${hmacDigest(secret, raw, verification)}`;\n return digestEquals(presented, expected, verification)\n ? OK\n : { ok: false, reason: \"hmac mismatch\" };\n }\n case \"hmac-timestamped\": {\n const { timestamp, signatures } = parseTimestampedHeader(presented);\n if (timestamp === undefined || !Number.isFinite(timestamp)) {\n return { ok: false, reason: \"no timestamp in the signature header\" };\n }\n if (signatures.length === 0) {\n return { ok: false, reason: \"no v1 signature in the header\" };\n }\n const nowMs = (options.now ?? new Date()).getTime();\n if (Math.abs(nowMs / 1000 - timestamp) > tolerance) {\n return { ok: false, reason: \"timestamp outside the replay window\" };\n }\n const expected = hmacDigest(\n secret,\n Buffer.concat([Buffer.from(`${timestamp}.`, \"utf8\"), raw]),\n verification,\n );\n // Every candidate is compared, so rotation does not change the timing.\n let matched = false;\n for (const signature of signatures) {\n if (digestEquals(signature, expected, verification)) matched = true;\n }\n return matched ? OK : { ok: false, reason: \"hmac mismatch\" };\n }\n }\n}\n\n/** Headers that would put a credential in a log or run journal. The configured signature\n * header joins them: it is an HMAC of the body under a live secret. */\nconst REDACTED_HEADERS = new Set([\n \"authorization\",\n \"proxy-authorization\",\n \"cookie\",\n \"set-cookie\",\n \"x-api-key\",\n \"x-webhook-token\",\n \"x-signature\",\n \"x-hub-signature\",\n \"x-hub-signature-256\",\n \"stripe-signature\",\n]);\n\nexport const REDACTED = \"[redacted]\";\n\nexport function redactHeaders(\n headers: Record<string, string>,\n extra?: string,\n): Record<string, string> {\n const redacted: Record<string, string> = {};\n for (const [name, value] of Object.entries(headers)) {\n const key = name.toLowerCase();\n redacted[key] =\n REDACTED_HEADERS.has(key) || (extra && key === extra.toLowerCase())\n ? REDACTED\n : value;\n }\n return redacted;\n}\n\n/** JSON and form bodies become objects; anything else stays decoded text, so a verified\n * XML or CSV payload is still reachable downstream. */\nexport function parseWebhookBody(raw: Buffer, contentType?: string): unknown {\n if (raw.length === 0) return undefined;\n const type = (contentType ?? \"\").split(\";\")[0]!.trim().toLowerCase();\n const text = raw.toString(\"utf8\");\n if (type === \"application/json\" || type.endsWith(\"+json\")) {\n try {\n return JSON.parse(text) as unknown;\n } catch {\n // A malformed body is still evidence; hand the text through.\n return text;\n }\n }\n if (type === \"application/x-www-form-urlencoded\") {\n return Object.fromEntries(new URLSearchParams(text));\n }\n return text;\n}\n","import { childLogger } from \"document-model\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport posix from \"node:path/posix\";\nimport { BodyTooLargeError, readBody, writeError } from \"./node-response.js\";\nimport type {\n IHttpScope,\n IWebhookScope,\n ScopedRouteHandle,\n WebhookPolicy,\n WebhookField,\n WebhookSpec,\n} from \"./types.js\";\nimport type { IWebhookStore } from \"./webhook-store.js\";\nimport {\n parseWebhookBody,\n redactHeaders,\n schemeHeader,\n verifyWebhook,\n} from \"./webhook-verify.js\";\n\nconst logger = childLogger([\"reactor-api\", \"webhooks\"]);\n\n/** The flat, token-addressed path family. */\nexport const WEBHOOK_SEGMENT = \"webhooks\";\n\nconst DEFAULT_MAX_BODY_BYTES = 1_048_576;\nconst DEFAULT_DEDUPE_TTL_SECONDS = 300;\n\nexport interface WebhookServiceOptions {\n store: IWebhookStore;\n basePath?: string;\n /** Public origin to advertise, e.g. https://switchboard.example. */\n publicUrl?: string;\n}\n\ntype Registration = { namespace: string; spec: WebhookSpec };\n\n/** One host route for `/webhooks/:token`, dispatching by token. The flat path leaks\n * neither package nor document; the namespace lives in the token record, which is also what stops one package's token reaching another's handler. */\nexport class WebhookService {\n readonly #store: IWebhookStore;\n readonly #path: string;\n readonly #publicUrl: string | undefined;\n // Layer 1, not the adapter: same dispatch, refusal and disposal path every package\n // route gets, so the two cannot drift on what a request means.\n #scope: IHttpScope | undefined;\n readonly #registrations = new Map<string, Registration>();\n #routes: ScopedRouteHandle[] = [];\n\n constructor({ store, basePath = \"/\", publicUrl }: WebhookServiceOptions) {\n this.#store = store;\n this.#path = posix.join(\"/\", basePath, WEBHOOK_SEGMENT);\n this.#publicUrl = publicUrl?.replace(/\\/+$/, \"\");\n }\n\n /** The scope the endpoint family serves from, handed over once the route service exists;\n * separate from the constructor only because that service takes this one as an option. */\n attach(scope: IHttpScope): void {\n this.#scope = scope;\n }\n\n async init(): Promise<void> {\n await this.#store.init();\n if (this.#routes.length) return;\n if (!this.#scope) {\n throw new Error(\n \"The webhook service has no HTTP scope; the host must call attach() before a package registers\",\n );\n }\n\n // Every method: a provider's verification round may probe with GET even when its\n // deliveries are POST, and refusing a method is the registration's call.\n\n // Truthfully public: the token in the path is the whole credential, and verification\n // is the registration's policy, not the host's auth — as is the rate, applied per registration in `#deliver`.\n this.#routes = [\n this.#scope.nodeRoute({\n method: [\"DELETE\", \"GET\", \"HEAD\", \"PATCH\", \"POST\", \"PUT\"],\n path: \":token\",\n auth: \"public\",\n handler: (req, res, ctx) => void this.#deliver(req, res, ctx.params),\n }),\n ];\n }\n\n dispose(): void {\n for (const handle of this.#routes) handle.dispose();\n this.#routes = [];\n this.#registrations.clear();\n }\n\n /** The facade a package's HTTP scope exposes as `scope.webhooks`. */\n scopeFor(namespace: string): IWebhookScope {\n return {\n hasPublicOrigin: this.hasPublicOrigin,\n register: async (spec: WebhookSpec) => {\n await this.init();\n const key = `${namespace}|${spec.name}`;\n this.#registrations.set(key, { namespace, spec });\n return {\n endpointFor: async (ownerKey: string) => {\n const row = await this.#store.ensure(\n namespace,\n spec.name,\n ownerKey,\n );\n return {\n token: row.token,\n url: this.urlFor(row.token),\n createdAt: row.createdAt,\n };\n },\n revoke: (ownerKey: string) =>\n this.#store.revoke(namespace, spec.name, ownerKey),\n list: async () =>\n (await this.#store.list(namespace, spec.name)).map((row) => ({\n key: row.ownerKey,\n token: row.token,\n url: this.urlFor(row.token),\n createdAt: row.createdAt,\n })),\n };\n },\n };\n }\n\n /** Releases every registration a package made. */\n disposeScope(namespace: string): void {\n for (const [key, registration] of this.#registrations) {\n if (registration.namespace === namespace) {\n this.#registrations.delete(key);\n }\n }\n }\n\n /** The URL to hand a provider. Absolute whenever the host knows its own origin: a\n * relative path is useless to the third party that has to call it. */\n urlFor(token: string): string {\n const path = posix.join(this.#path, token);\n return this.#publicUrl ? `${this.#publicUrl}${path}` : path;\n }\n\n /** Whether `urlFor` can produce something a provider could call. */\n get hasPublicOrigin(): boolean {\n return this.#publicUrl !== undefined;\n }\n\n async #deliver(\n req: IncomingMessage,\n res: ServerResponse,\n params: Record<string, string>,\n ): Promise<void> {\n const token = params.token;\n if (!token) {\n writeError(res, 404, \"Unknown endpoint\");\n return;\n }\n\n try {\n const row = await this.#store.find(token);\n // Unknown, malformed and disarmed all answer this same 404, so a prober cannot tell\n // a live endpoint from a dead one; a live endpoint's verification failure answers 401, the caller having proved the token exists by holding it.\n if (!row) {\n writeError(res, 404, \"Unknown endpoint\");\n return;\n }\n\n const registrationKey = `${row.namespace}|${row.endpoint}`;\n const registration = this.#registrations.get(registrationKey);\n if (!registration) {\n // The token is real but its package is not loaded on this host.\n writeError(res, 503, \"Endpoint temporarily unavailable\");\n return;\n }\n\n const { spec } = registration;\n const method = (req.method ?? \"POST\").toUpperCase();\n\n const perEndpoint = spec.policyFor\n ? await spec.policyFor(row.ownerKey)\n : {};\n if (!perEndpoint) {\n // Not armed. Answers as an unknown token does, deliberately.\n writeError(res, 404, \"Unknown endpoint\");\n return;\n }\n\n // Declared defaults, then what this endpoint carries. Only `defaults` participates,\n // which is why the spec keeps its policy fields under their own key.\n const policy: WebhookPolicy = { ...spec.defaults, ...perEndpoint };\n\n if (policy.methods && !policy.methods.includes(method)) {\n writeError(res, 405, \"Method not allowed\");\n return;\n }\n\n let raw: Buffer;\n try {\n raw = await readBody(\n req,\n policy.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES,\n );\n } catch (error) {\n if (error instanceof BodyTooLargeError) {\n res.setHeader(\"connection\", \"close\");\n res.once(\"finish\", () => req.destroy());\n writeError(res, 413, \"Payload too large\");\n return;\n }\n throw error;\n }\n\n const verification = policy.verify;\n if (verification) {\n const result = verifyWebhook({\n verification,\n headers: headerRecord(req),\n raw,\n });\n if (!result.ok) {\n // The namespace starts with `@`, the logger's replacement token; passed\n // positionally it stays a value, not a placeholder to be substituted away.\n logger.warn(\n \"Rejected webhook delivery for @package/@endpoint: @reason\",\n row.namespace,\n row.endpoint,\n result.reason,\n );\n writeError(res, 401, \"Signature verification failed\");\n return;\n }\n }\n\n // A fixed base: only the query is read from this, so the request's own\n // origin never enters it and cannot be spoofed through it.\n const url = new URL(req.url ?? \"/\", \"http://localhost\");\n const queryParams = Object.fromEntries(url.searchParams);\n const signatureHeader = verification\n ? schemeHeader(verification)\n : undefined;\n const headers = headerRecord(req);\n const body = parseWebhookBody(raw, headers[\"content-type\"]);\n\n // The provider's verification round: echo the value, invoke nothing. From the merged\n // policy, not the registration — the echoed field is per-endpoint configuration.\n const challenge = challengeValue(\n policy.challengeField,\n queryParams,\n headers,\n body,\n );\n if (challenge !== undefined) {\n res.statusCode = 200;\n res.setHeader(\"content-type\", \"text/plain\");\n res.end(challenge);\n return;\n }\n\n if (policy.dedupe) {\n const key = dedupeKey(policy.dedupe.field, queryParams, headers, body);\n if (\n key !== undefined &&\n (await this.#store.seen(\n token,\n key,\n policy.dedupe.ttlSeconds ?? DEFAULT_DEDUPE_TTL_SECONDS,\n ))\n ) {\n // A redelivery is not an error: answer as though it succeeded, so the\n // provider stops retrying, but run nothing twice.\n res.statusCode = 200;\n res.end();\n return;\n }\n }\n\n const reply = await spec.onRequest({\n key: row.ownerKey,\n method,\n path: url.pathname,\n queryParams,\n headers: redactHeaders(headers, signatureHeader),\n raw,\n body,\n });\n\n res.statusCode = reply.status;\n if (reply.body !== undefined && method !== \"HEAD\") {\n res.setHeader(\"content-type\", reply.contentType ?? \"text/plain\");\n res.end(reply.body);\n } else {\n res.end();\n }\n } catch (error) {\n // Not the token or the URL: the token is the capability, and the URL carries it.\n logger.error(\n \"Webhook delivery failed for @method\",\n req.method,\n error as Error,\n );\n writeError(res, 500, \"Internal server error\");\n }\n }\n}\n\nfunction headerRecord(req: IncomingMessage): Record<string, string> {\n const headers: Record<string, string> = {};\n for (const [name, value] of Object.entries(req.headers)) {\n if (value === undefined) continue;\n headers[name.toLowerCase()] = Array.isArray(value)\n ? value.join(\", \")\n : value;\n }\n return headers;\n}\n\nfunction scalar(value: unknown): string | undefined {\n if (typeof value === \"string\" && value !== \"\") return value;\n if (typeof value === \"number\") return String(value);\n return undefined;\n}\n\n/** Walks a dot-separated path into the parsed body. */\nfunction bodyPath(path: string, body: unknown): string | undefined {\n let current: unknown = body;\n for (const segment of path.split(\".\")) {\n if (!current || typeof current !== \"object\") return undefined;\n current = (current as Record<string, unknown>)[segment];\n }\n return scalar(current);\n}\n\n/** Resolves where a provider put a value. A bare string means query first, then a\n * top-level body field; `{ header }` and `{ body }` reach what that cannot — GitHub's delivery id is a header, Stripe's event id is nested. */\nfunction fieldValue(\n field: WebhookField,\n queryParams: Record<string, string>,\n headers: Record<string, string>,\n body: unknown,\n): string | undefined {\n if (typeof field === \"object\") {\n return \"header\" in field\n ? scalar(headers[field.header.toLowerCase()])\n : bodyPath(field.body, body);\n }\n const fromQuery = scalar(queryParams[field]);\n if (fromQuery !== undefined) return fromQuery;\n return body && typeof body === \"object\"\n ? scalar((body as Record<string, unknown>)[field])\n : undefined;\n}\n\nfunction challengeValue(\n field: WebhookField | undefined,\n queryParams: Record<string, string>,\n headers: Record<string, string>,\n body: unknown,\n): string | undefined {\n return field === undefined\n ? undefined\n : fieldValue(field, queryParams, headers, body);\n}\n\nfunction dedupeKey(\n field: WebhookField,\n queryParams: Record<string, string>,\n headers: Record<string, string>,\n body: unknown,\n): string | undefined {\n return fieldValue(field, queryParams, headers, body);\n}\n","import type { IRelationalDb } from \"@powerhousedao/shared/processors\";\nimport { randomBytes } from \"node:crypto\";\n\n/**\n * Where webhook tokens live. Core-owned and relational rather than per-host, so\n * any host in a fleet can serve any endpoint: a provider's registered URL keeps\n * working after a restart, a redeploy or a request landing on another replica.\n */\nexport interface WebhookEndpointRow {\n token: string;\n /** The owning package's npm name. */\n namespace: string;\n /** The registration within that package. */\n endpoint: string;\n /** The caller's own key, e.g. a document id. Never appears in the URL. */\n ownerKey: string;\n createdAt: string;\n}\n\nexport interface IWebhookStore {\n init(): Promise<void>;\n /** Returns the existing token for this key, or mints one. */\n ensure(\n namespace: string,\n endpoint: string,\n ownerKey: string,\n ): Promise<WebhookEndpointRow>;\n find(token: string): Promise<WebhookEndpointRow | undefined>;\n list(namespace: string, endpoint?: string): Promise<WebhookEndpointRow[]>;\n revoke(namespace: string, endpoint: string, ownerKey: string): Promise<void>;\n /** True when this delivery has been seen before, within the TTL. */\n seen(token: string, key: string, ttlSeconds: number): Promise<boolean>;\n}\n\nconst TOKEN_BYTES = 16;\nexport const TOKEN_PATTERN = /^[0-9a-f]{32}$/;\n\n/** Opaque and unguessable: the URL is a bearer capability held by a third party. */\nexport function newWebhookToken(): string {\n return randomBytes(TOKEN_BYTES).toString(\"hex\");\n}\n\nconst NAMESPACE = \"reactor_webhooks\";\n\ntype Schema = {\n webhook_endpoints: {\n token: string;\n namespace: string;\n endpoint: string;\n owner_key: string;\n created_at: string;\n };\n webhook_deliveries: {\n token: string;\n dedupe_key: string;\n seen_at: string;\n /** When the key ages out, from the TTL it was seen with; null on legacy rows. */\n expires_at: string | null;\n /** Who won the insert; see the comment in seen(). */\n claim_id: string;\n };\n};\n\n/** Relational implementation, over the reactor's own database. */\nexport class RelationalWebhookStore implements IWebhookStore {\n #db: IRelationalDb<Schema> | undefined;\n\n constructor(private readonly relationalDb: IRelationalDb) {}\n\n async init(): Promise<void> {\n if (this.#db) return;\n const db = await this.relationalDb.createNamespace<Schema>(NAMESPACE);\n\n await db.schema\n .createTable(\"webhook_endpoints\")\n .ifNotExists()\n .addColumn(\"token\", \"text\", (col) => col.primaryKey())\n .addColumn(\"namespace\", \"text\", (col) => col.notNull())\n .addColumn(\"endpoint\", \"text\", (col) => col.notNull())\n .addColumn(\"owner_key\", \"text\", (col) => col.notNull())\n .addColumn(\"created_at\", \"text\", (col) => col.notNull())\n .execute();\n\n // One token per (package, registration, key): re-registering an endpoint\n // must not mint a second URL for something a provider already knows.\n await db.schema\n .createIndex(\"webhook_endpoints_owner\")\n .ifNotExists()\n .on(\"webhook_endpoints\")\n .columns([\"namespace\", \"endpoint\", \"owner_key\"])\n .unique()\n .execute();\n\n await db.schema\n .createTable(\"webhook_deliveries\")\n .ifNotExists()\n .addColumn(\"token\", \"text\", (col) => col.notNull())\n .addColumn(\"dedupe_key\", \"text\", (col) => col.notNull())\n .addColumn(\"seen_at\", \"text\", (col) => col.notNull())\n .addColumn(\"claim_id\", \"text\", (col) => col.notNull())\n .execute();\n\n // Additive migration for tables created before per-row expiry.\n try {\n await db.schema\n .alterTable(\"webhook_deliveries\")\n .addColumn(\"expires_at\", \"text\")\n .execute();\n } catch {\n // column already exists\n }\n\n await db.schema\n .createIndex(\"webhook_deliveries_key\")\n .ifNotExists()\n .on(\"webhook_deliveries\")\n .columns([\"token\", \"dedupe_key\"])\n .unique()\n .execute();\n\n // Every delivery prunes by expiry; unindexed that is a scan of the whole\n // table. `seen_at` still serves the prune of legacy rows with no expiry.\n await db.schema\n .createIndex(\"webhook_deliveries_expires_at\")\n .ifNotExists()\n .on(\"webhook_deliveries\")\n .columns([\"expires_at\"])\n .execute();\n await db.schema\n .createIndex(\"webhook_deliveries_seen_at\")\n .ifNotExists()\n .on(\"webhook_deliveries\")\n .columns([\"seen_at\"])\n .execute();\n\n this.#db = db;\n }\n\n get #handle(): IRelationalDb<Schema> {\n if (!this.#db) throw new Error(\"Webhook store used before init()\");\n return this.#db;\n }\n\n async ensure(\n namespace: string,\n endpoint: string,\n ownerKey: string,\n ): Promise<WebhookEndpointRow> {\n const existing = await this.#handle\n .selectFrom(\"webhook_endpoints\")\n .selectAll()\n .where(\"namespace\", \"=\", namespace)\n .where(\"endpoint\", \"=\", endpoint)\n .where(\"owner_key\", \"=\", ownerKey)\n .executeTakeFirst();\n if (existing) return toRow(existing);\n\n const row: Schema[\"webhook_endpoints\"] = {\n token: newWebhookToken(),\n namespace,\n endpoint,\n owner_key: ownerKey,\n created_at: new Date().toISOString(),\n };\n\n await this.#handle\n .insertInto(\"webhook_endpoints\")\n .values(row)\n // Two hosts arming the same endpoint at once must agree on one token.\n .onConflict((oc) =>\n oc.columns([\"namespace\", \"endpoint\", \"owner_key\"]).doNothing(),\n )\n .execute();\n\n const settled = await this.#handle\n .selectFrom(\"webhook_endpoints\")\n .selectAll()\n .where(\"namespace\", \"=\", namespace)\n .where(\"endpoint\", \"=\", endpoint)\n .where(\"owner_key\", \"=\", ownerKey)\n .executeTakeFirst();\n\n return settled ? toRow(settled) : toRow(row);\n }\n\n async find(token: string): Promise<WebhookEndpointRow | undefined> {\n if (!TOKEN_PATTERN.test(token)) return undefined;\n const found = await this.#handle\n .selectFrom(\"webhook_endpoints\")\n .selectAll()\n .where(\"token\", \"=\", token)\n .executeTakeFirst();\n return found ? toRow(found) : undefined;\n }\n\n async list(\n namespace: string,\n endpoint?: string,\n ): Promise<WebhookEndpointRow[]> {\n let query = this.#handle\n .selectFrom(\"webhook_endpoints\")\n .selectAll()\n .where(\"namespace\", \"=\", namespace);\n if (endpoint) query = query.where(\"endpoint\", \"=\", endpoint);\n return (await query.execute()).map(toRow);\n }\n\n async revoke(\n namespace: string,\n endpoint: string,\n ownerKey: string,\n ): Promise<void> {\n await this.#handle\n .deleteFrom(\"webhook_endpoints\")\n .where(\"namespace\", \"=\", namespace)\n .where(\"endpoint\", \"=\", endpoint)\n .where(\"owner_key\", \"=\", ownerKey)\n .execute();\n }\n\n async seen(token: string, key: string, ttlSeconds: number): Promise<boolean> {\n const now = Date.now();\n const nowIso = new Date(now).toISOString();\n const cutoff = new Date(now - ttlSeconds * 1000).toISOString();\n\n // Prune first, so a key that has aged out is redeliverable rather than\n // rejected forever. Each row expires on the TTL it was seen with.\n await this.#handle\n .deleteFrom(\"webhook_deliveries\")\n .where((eb) =>\n eb.or([\n eb(\"expires_at\", \"<\", nowIso),\n eb.and([eb(\"expires_at\", \"is\", null), eb(\"seen_at\", \"<\", cutoff)]),\n ]),\n )\n .execute();\n // This token's own key also ages out under its current TTL, if shorter.\n await this.#handle\n .deleteFrom(\"webhook_deliveries\")\n .where(\"token\", \"=\", token)\n .where(\"dedupe_key\", \"=\", key)\n .where(\"seen_at\", \"<\", cutoff)\n .execute();\n\n // Insert-then-read-back rather than trusting an affected-row count: what\n // \"on conflict do nothing\" reports differs by driver, and reading it wrong\n // means either every delivery looks like a redelivery or none does. The\n // claim id settles it without a transaction, so two hosts racing the same\n // delivery still agree on which one runs it.\n const claimId = randomBytes(16).toString(\"hex\");\n await this.#handle\n .insertInto(\"webhook_deliveries\")\n .values({\n token,\n dedupe_key: key,\n seen_at: nowIso,\n expires_at: new Date(now + ttlSeconds * 1000).toISOString(),\n claim_id: claimId,\n })\n .onConflict((oc) => oc.columns([\"token\", \"dedupe_key\"]).doNothing())\n .execute();\n\n const settled = await this.#handle\n .selectFrom(\"webhook_deliveries\")\n .select(\"claim_id\")\n .where(\"token\", \"=\", token)\n .where(\"dedupe_key\", \"=\", key)\n .executeTakeFirst();\n\n // Our claim stands: this is the first delivery. Anyone else's: a retry.\n return settled?.claim_id !== claimId;\n }\n}\n\nfunction toRow(row: Schema[\"webhook_endpoints\"]): WebhookEndpointRow {\n return {\n token: row.token,\n namespace: row.namespace,\n endpoint: row.endpoint,\n ownerKey: row.owner_key,\n createdAt: row.created_at,\n };\n}\n\n/** In-memory store, for hosts with no relational database and for tests. */\nexport class MemoryWebhookStore implements IWebhookStore {\n readonly #byToken = new Map<string, WebhookEndpointRow>();\n readonly #deliveries = new Map<\n string,\n { seenAt: number; expiresAt: number }\n >();\n\n init(): Promise<void> {\n return Promise.resolve();\n }\n\n ensure(\n namespace: string,\n endpoint: string,\n ownerKey: string,\n ): Promise<WebhookEndpointRow> {\n for (const row of this.#byToken.values()) {\n if (\n row.namespace === namespace &&\n row.endpoint === endpoint &&\n row.ownerKey === ownerKey\n ) {\n return Promise.resolve(row);\n }\n }\n const row: WebhookEndpointRow = {\n token: newWebhookToken(),\n namespace,\n endpoint,\n ownerKey,\n createdAt: new Date().toISOString(),\n };\n this.#byToken.set(row.token, row);\n return Promise.resolve(row);\n }\n\n find(token: string): Promise<WebhookEndpointRow | undefined> {\n return Promise.resolve(this.#byToken.get(token));\n }\n\n list(namespace: string, endpoint?: string): Promise<WebhookEndpointRow[]> {\n return Promise.resolve(\n [...this.#byToken.values()].filter(\n (row) =>\n row.namespace === namespace &&\n (endpoint === undefined || row.endpoint === endpoint),\n ),\n );\n }\n\n revoke(namespace: string, endpoint: string, ownerKey: string): Promise<void> {\n for (const [token, row] of this.#byToken) {\n if (\n row.namespace === namespace &&\n row.endpoint === endpoint &&\n row.ownerKey === ownerKey\n ) {\n this.#byToken.delete(token);\n }\n }\n return Promise.resolve();\n }\n\n seen(token: string, key: string, ttlSeconds: number): Promise<boolean> {\n const now = Date.now();\n for (const [k, entry] of this.#deliveries) {\n if (entry.expiresAt < now) this.#deliveries.delete(k);\n }\n const composite = `${token}|${key}`;\n const existing = this.#deliveries.get(composite);\n if (existing && existing.seenAt >= now - ttlSeconds * 1000) {\n return Promise.resolve(true);\n }\n this.#deliveries.set(composite, {\n seenAt: now,\n expiresAt: now + ttlSeconds * 1000,\n });\n return Promise.resolve(false);\n }\n}\n","import {\n buildSubgraphSchema,\n type GraphQLResolverMap,\n type GraphQLSchemaModule,\n} from \"@apollo/subgraph\";\nimport { typeDefs as scalarsTypeDefs } from \"@powerhousedao/document-engineering/graphql\";\nimport type { Context } from \"@powerhousedao/reactor-api\";\nimport type {\n DocumentModelGlobalState,\n DocumentModelModule,\n} from \"@powerhousedao/shared/document-model\";\nimport { camelCase, pascalCase } from \"change-case\";\nimport { childLogger } from \"document-model\";\nimport {\n type ASTNode,\n type DefinitionNode,\n type DocumentNode,\n Kind,\n Lexer,\n type NameNode,\n parse,\n print,\n Source,\n TokenKind,\n visit,\n} from \"graphql\";\nimport { gql } from \"graphql-tag\";\nimport { GraphQLJSON, GraphQLJSONObject } from \"graphql-type-json\";\n\nconst logger = childLogger([\"reactor-api\", \"create-schema\"]);\n\n/**\n * Revision type - matches the definition in reactor/schema.graphql.\n * Used by PHDocument and document mutation results.\n */\nconst RevisionType = `\n type Revision {\n scope: String!\n revision: Int!\n }\n`;\n\n/**\n * Strip scalar definitions from a DocumentNode to avoid duplicates\n * when combining with other schemas that define the same scalars.\n */\nconst stripScalarDefinitions = (doc: DocumentNode): string => {\n const filteredDefinitions = doc.definitions.filter(\n (def) => def.kind !== Kind.SCALAR_TYPE_DEFINITION,\n );\n return print({ kind: Kind.DOCUMENT, definitions: filteredDefinitions });\n};\n\n/**\n * Type-system definition kinds that GraphQL requires to be uniquely named.\n * A subgraph SDL with two definitions sharing a name fails federation\n * composition (\"There can be only one type named X\"), which is fatal to the\n * whole gateway. We dedupe these by name; field/operation/extension nodes are\n * left untouched.\n */\nconst TYPE_DEFINITION_KINDS = new Set<Kind>([\n Kind.OBJECT_TYPE_DEFINITION,\n Kind.ENUM_TYPE_DEFINITION,\n Kind.INPUT_OBJECT_TYPE_DEFINITION,\n Kind.INTERFACE_TYPE_DEFINITION,\n Kind.UNION_TYPE_DEFINITION,\n Kind.SCALAR_TYPE_DEFINITION,\n]);\n\n/**\n * Drop duplicate type-system definitions by name, keeping the first occurrence.\n * Deduping is by name across ALL kinds (a `type` and an `enum` sharing a name\n * collide in GraphQL too), so the first definition of a given name wins\n * regardless of kind. State types are emitted before operation types, so\n * keep-first preserves the authoritative state definition. This heals a document\n * model that defines the same name twice (global+local, state+operation, or\n * twice in one scope) so the assembled subgraph SDL composes instead of crashing\n * the gateway (Sentry #917).\n */\nconst dedupeTypeDefinitions = (doc: DocumentNode): DocumentNode => {\n const seen = new Set<string>();\n const definitions = doc.definitions.filter((def) => {\n if (!TYPE_DEFINITION_KINDS.has(def.kind)) return true;\n const name = (def as { name?: { value: string } }).name?.value;\n if (!name) return true;\n if (seen.has(name)) {\n // A duplicate here would otherwise crash supergraph composition; log it so\n // production has a breadcrumb of which model shipped a duplicate name.\n logger.debug(`Dropping duplicate type definition: ${name}`);\n return false;\n }\n seen.add(name);\n return true;\n });\n return { kind: Kind.DOCUMENT, definitions };\n};\n\nconst EMPTY_DOCUMENT: DocumentNode = { kind: Kind.DOCUMENT, definitions: [] };\n\nconst OUTPUT_TYPE_KINDS = [\n Kind.OBJECT_TYPE_DEFINITION,\n Kind.OBJECT_TYPE_EXTENSION,\n Kind.ENUM_TYPE_DEFINITION,\n Kind.ENUM_TYPE_EXTENSION,\n Kind.UNION_TYPE_DEFINITION,\n Kind.UNION_TYPE_EXTENSION,\n Kind.INTERFACE_TYPE_DEFINITION,\n Kind.INTERFACE_TYPE_EXTENSION,\n];\n\n// Kinds whose names get prefixed: state schemas (inputs stripped) and operation schemas.\nconst STATE_PREFIX_KINDS = new Set<Kind>(OUTPUT_TYPE_KINDS);\nconst ALL_PREFIX_KINDS = new Set<Kind>([\n ...OUTPUT_TYPE_KINDS,\n Kind.INPUT_OBJECT_TYPE_DEFINITION,\n Kind.INPUT_OBJECT_TYPE_EXTENSION,\n]);\n\n// Nodes whose `name` is a type name: definitions, extensions and references.\nconst TYPE_NAME_KINDS = new Set<Kind>([\n ...ALL_PREFIX_KINDS,\n Kind.SCALAR_TYPE_DEFINITION,\n Kind.SCALAR_TYPE_EXTENSION,\n Kind.NAMED_TYPE,\n]);\n\n// Stub local state types dropped from legacy models.\nconst LOCAL_STATE_STUBS = new Set([\n \"AccountSnapshotLocalState\",\n \"BudgetStatementLocalState\",\n \"ScopeFrameworkLocalState\",\n]);\n\n/** Parse SDL; blank or comment-only input yields an empty document. */\nfunction parseSdl(sdl: string): DocumentNode {\n const source = new Source(sdl);\n if (new Lexer(source).advance().kind === TokenKind.EOF) return EMPTY_DOCUMENT;\n try {\n return parse(source, { noLocation: true });\n } catch (error) {\n // Retry without stray semicolons, which GraphQL rejects.\n const withoutSemicolons = sdl.replaceAll(\";\", \"\");\n if (withoutSemicolons === sdl) throw error;\n return parse(withoutSemicolons, { noLocation: true });\n }\n}\n\nfunction definedTypeNames(\n doc: DocumentNode,\n kinds: ReadonlySet<Kind>,\n): string[] {\n return doc.definitions\n .filter((def) => kinds.has(def.kind))\n .map((def) => (def as DefinitionNode & { name: NameNode }).name.value);\n}\n\n/** Prefix type definition names and type references found in `names`. */\nfunction prefixTypeNames(\n doc: DocumentNode,\n prefix: string,\n names: ReadonlySet<string>,\n): DocumentNode {\n return visit(doc, {\n enter(node: ASTNode) {\n if (!TYPE_NAME_KINDS.has(node.kind)) return undefined;\n const { name } = node as ASTNode & { name: NameNode };\n if (!names.has(name.value)) return undefined;\n return { ...node, name: { ...name, value: `${prefix}_${name.value}` } };\n },\n });\n}\n\n/** State schema definitions without inputs, `DateTime` or the given object types. */\nfunction stateTypeDefinitions(\n sdl: string,\n droppedObjectTypes: ReadonlySet<string> = new Set(),\n): DefinitionNode[] {\n return parseSdl(sdl).definitions.filter(\n (def) =>\n def.kind !== Kind.INPUT_OBJECT_TYPE_DEFINITION &&\n def.kind !== Kind.INPUT_OBJECT_TYPE_EXTENSION &&\n !(\n def.kind === Kind.SCALAR_TYPE_DEFINITION &&\n def.name.value === \"DateTime\"\n ) &&\n !(\n def.kind === Kind.OBJECT_TYPE_DEFINITION &&\n droppedObjectTypes.has(def.name.value)\n ),\n );\n}\n\n/**\n * Prefixed operation schemas per module. The first definition of each module\n * carries a \"Module: <Name>\" description unless it has its own.\n */\nfunction buildModuleSchemas(\n specification: DocumentModelGlobalState[\"specifications\"][0] | undefined,\n documentName: string,\n allTypeNames: string[],\n hasValidSchema: (schema: string | null | undefined) => boolean,\n): string {\n const names = new Set(allTypeNames);\n return (\n specification?.modules\n .map((module) => {\n const definitions = module.operations\n .filter((op) => hasValidSchema(op.schema))\n .flatMap((op) => {\n const doc = parseSdl(op.schema ?? \"\");\n const opNames = new Set([\n ...names,\n ...definedTypeNames(doc, ALL_PREFIX_KINDS),\n ]);\n return prefixTypeNames(doc, documentName, opNames).definitions;\n });\n if (definitions.length === 0) return \"\";\n const [first, ...rest] = definitions;\n const header =\n \"description\" in first && !first.description\n ? {\n ...first,\n description: {\n kind: Kind.STRING,\n value: `Module: ${pascalCase(module.name)}`,\n block: true,\n },\n }\n : first;\n return print({\n kind: Kind.DOCUMENT,\n definitions: [header as DefinitionNode, ...rest],\n });\n })\n .filter(Boolean)\n .join(\"\\n\") ?? \"\"\n );\n}\n\nexport const buildSubgraphSchemaModule = (\n documentModels: DocumentModelModule[],\n resolvers: GraphQLResolverMap<Context>,\n typeDefs: DocumentNode,\n): GraphQLSchemaModule => {\n const newResolvers = {\n ...resolvers,\n JSONObject: GraphQLJSONObject,\n Unknown: GraphQLJSON,\n };\n\n return {\n typeDefs: getDocumentModelTypeDefs(documentModels, typeDefs),\n resolvers: newResolvers,\n };\n};\nexport const createSchema = (\n documentModels: DocumentModelModule[],\n resolvers: GraphQLResolverMap<Context>,\n typeDefs: DocumentNode,\n) => {\n // Array form: @apollo/subgraph 2.15 dropped the bare-module overload.\n return buildSubgraphSchema([\n buildSubgraphSchemaModule(documentModels, resolvers, typeDefs),\n ]);\n};\n\n/**\n * Create a merged GraphQL schema from multiple subgraph modules.\n * Uses buildSubgraphSchema's array overload to combine type definitions\n * and resolvers from multiple subgraphs into a single executable schema.\n */\nexport const createMergedSchema = (modules: GraphQLSchemaModule[]) => {\n return buildSubgraphSchema(modules);\n};\n\nexport function getDocumentModelSchemaName(\n documentModel: DocumentModelGlobalState,\n) {\n return pascalCase(documentModel.name.replaceAll(\"/\", \" \"));\n}\n\nexport const getDocumentModelTypeDefs = (\n documentModels: DocumentModelModule[],\n typeDefs: DocumentNode,\n) => {\n let dmSchema = \"\";\n\n const addedDocumentModels = new Set<string>();\n documentModels.forEach(({ documentModel }) => {\n const dmSchemaName = getDocumentModelSchemaName(documentModel.global);\n if (addedDocumentModels.has(dmSchemaName)) {\n logger.debug(\n `Skipping document model with duplicate name: ${dmSchemaName}`,\n );\n return;\n }\n addedDocumentModels.add(dmSchemaName);\n // Use only the latest specification to avoid duplicate type definitions\n // when a document model has multiple versions (e.g. v1, v2).\n const latestSpec = documentModel.global.specifications.at(-1);\n const globalSchema = latestSpec?.state.global.schema ?? \"\";\n const localSchema = latestSpec?.state.local.schema ?? \"\";\n const definitions = [\n ...stateTypeDefinitions(globalSchema),\n ...stateTypeDefinitions(localSchema, LOCAL_STATE_STUBS),\n ];\n const stateDoc: DocumentNode = { kind: Kind.DOCUMENT, definitions };\n const prefixed = prefixTypeNames(\n stateDoc,\n dmSchemaName,\n new Set(definedTypeNames(stateDoc, STATE_PREFIX_KINDS)),\n );\n if (definitions.length > 0) dmSchema += `${print(prefixed)}\\n`;\n dmSchema += `\n type ${dmSchemaName} implements IDocument {\n id: String!\n name: String!\n documentType: String!\n operations(skip: Int, first: Int): [Operation!]!\n revision: Int!\n createdAtUtcIso: DateTime!\n lastModifiedAtUtcIso: DateTime!\n ${dmSchemaName !== \"DocumentModel\" ? `initialState: ${dmSchemaName}_${dmSchemaName}State!` : \"\"}\n ${dmSchemaName !== \"DocumentModel\" ? `state: ${dmSchemaName}_${dmSchemaName}State!` : \"\"}\n stateJSON: JSONObject\n }\\n`;\n });\n\n // add the mutation and query types\n const schema = gql`\n scalar JSONObject\n scalar AttachmentRef\n # Codegen scalars not in the document-engineering set.\n scalar Unknown\n scalar Address\n ${scalarsTypeDefs.join(\"\\n\").replaceAll(\";\", \"\")}\n\n type PHOperationContext {\n signer: Signer\n }\n\n type Signer {\n user: SignerUser\n app: SignerApp\n signatures: [String!]!\n }\n\n type SignerUser {\n address: String!\n networkId: String!\n chainId: Int!\n }\n\n type SignerApp {\n name: String!\n key: String!\n }\n\n type Operation {\n id: String!\n type: String!\n index: Int!\n timestampUtcMs: DateTime!\n hash: String!\n skip: Int\n inputText: String\n error: String\n context: PHOperationContext\n }\n\n interface IDocument {\n id: String!\n name: String!\n documentType: String!\n revision: Int!\n createdAtUtcIso: DateTime!\n lastModifiedAtUtcIso: DateTime!\n operations(first: Int, skip: Int): [Operation!]!\n stateJSON: JSONObject\n }\n ${dmSchema}\n\n type GqlDocument implements IDocument {\n id: String!\n name: String!\n documentType: String!\n revision: Int!\n createdAtUtcIso: DateTime!\n lastModifiedAtUtcIso: DateTime!\n operations(first: Int, skip: Int): [Operation!]!\n stateJSON: JSONObject\n }\n\n type DriveDocument implements IDocument {\n id: String!\n name: String!\n documentType: String!\n revision: Int!\n createdAtUtcIso: DateTime!\n lastModifiedAtUtcIso: DateTime!\n operations(first: Int, skip: Int): [Operation!]!\n stateJSON: JSONObject\n }\n\n ${stripScalarDefinitions(typeDefs)}\n `;\n\n return dedupeTypeDefinitions(schema);\n};\n\n/**\n * Extract the names of types defined in a GraphQL schema.\n * Unparseable schemas yield no names.\n */\nfunction extractTypeNames(schema: string): string[] {\n try {\n return definedTypeNames(parseSdl(schema), ALL_PREFIX_KINDS);\n } catch (error) {\n logger.debug(`Skipping unparseable schema: ${String(error)}`);\n return [];\n }\n}\n\n/**\n * Print the input type definitions of a GraphQL schema.\n * @param excludeTypeNames - Input type names to leave out\n */\nfunction extractInputTypeDefinitions(\n schema: string,\n excludeTypeNames: Set<string> = new Set(),\n): string {\n const definitions = parseSdl(schema).definitions.filter(\n (def) =>\n def.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION &&\n !excludeTypeNames.has(def.name.value),\n );\n if (definitions.length === 0) return \"\";\n return print({ kind: Kind.DOCUMENT, definitions });\n}\n\n/**\n * AST type node shape for recursive type conversion.\n */\ntype GraphQLTypeNode = {\n kind: Kind;\n name?: { value: string };\n type?: GraphQLTypeNode;\n};\n\n/**\n * Extract the root state type name from a scope's GraphQL schema.\n * Uses the naming convention: {DocumentName}State for global,\n * {DocumentName}{PascalScope}State for other scopes (e.g., DocumentDriveLocalState).\n * Falls back to the last ObjectTypeDefinition (root types are conventionally last).\n */\nfunction extractRootTypeName(\n schema: string,\n documentName: string,\n scopeName: string,\n): string | null {\n try {\n const ast = parse(schema);\n\n // Try conventions:\n // 1. {DocumentName}State for global, {DocumentName}{Scope}State otherwise\n // 2. {DocumentName}GlobalState (DocumentModel uses this variant)\n const scopeSuffix = scopeName === \"global\" ? \"\" : pascalCase(scopeName);\n const candidates = [\n `${documentName}${scopeSuffix}State`,\n `${documentName}${pascalCase(scopeName)}State`,\n ];\n\n let lastObjectType: string | null = null;\n for (const def of ast.definitions) {\n if (def.kind === Kind.OBJECT_TYPE_DEFINITION) {\n if (candidates.includes(def.name.value)) {\n return def.name.value;\n }\n lastObjectType = def.name.value;\n }\n }\n\n // Fallback: last object type (root state types are defined last by convention)\n return lastObjectType;\n } catch {\n // ignore parse errors\n }\n return null;\n}\n\n/**\n * Convert a GraphQL output type AST node to an optional input type string.\n * Strips non-null markers and converts object type references to Input suffix.\n */\nfunction convertTypeNodeToInput(\n typeNode: GraphQLTypeNode,\n objectNames: Set<string>,\n unionNames: Set<string>,\n interfaceNames: Set<string>,\n): string {\n if (typeNode.kind === Kind.NON_NULL_TYPE && typeNode.type) {\n return convertTypeNodeToInput(\n typeNode.type,\n objectNames,\n unionNames,\n interfaceNames,\n );\n }\n if (typeNode.kind === Kind.LIST_TYPE && typeNode.type) {\n const inner = convertTypeNodeToInput(\n typeNode.type,\n objectNames,\n unionNames,\n interfaceNames,\n );\n return `[${inner}]`;\n }\n if (typeNode.kind === Kind.NAMED_TYPE && typeNode.name) {\n const name = typeNode.name.value;\n if (objectNames.has(name)) return `${name}Input`;\n if (unionNames.has(name) || interfaceNames.has(name)) return \"JSONObject\";\n return name;\n }\n return \"JSONObject\";\n}\n\n/**\n * Generate GraphQL input type definitions from a state schema string.\n * Converts output type definitions to input types with all fields optional.\n * - Object type references get Input suffix\n * - Union/interface references become JSONObject\n * - Enums and scalars remain unchanged\n */\nfunction generateStateInputTypes(\n stateSchema: string,\n excludeTypeNames?: Set<string>,\n): string {\n if (!stateSchema || !stateSchema.trim()) return \"\";\n\n let ast;\n try {\n ast = parse(stateSchema);\n } catch {\n return \"\";\n }\n\n const enumNames = new Set<string>();\n const unionNames = new Set<string>();\n const interfaceNames = new Set<string>();\n const objectNames = new Set<string>();\n const existingInputNames = new Set<string>();\n\n for (const def of ast.definitions) {\n switch (def.kind) {\n case Kind.ENUM_TYPE_DEFINITION:\n enumNames.add(def.name.value);\n break;\n case Kind.UNION_TYPE_DEFINITION:\n unionNames.add(def.name.value);\n break;\n case Kind.INTERFACE_TYPE_DEFINITION:\n interfaceNames.add(def.name.value);\n break;\n case Kind.OBJECT_TYPE_DEFINITION:\n objectNames.add(def.name.value);\n break;\n case Kind.INPUT_OBJECT_TYPE_DEFINITION:\n existingInputNames.add(def.name.value);\n break;\n }\n }\n\n const inputTypes: string[] = [];\n\n for (const def of ast.definitions) {\n if (def.kind !== Kind.OBJECT_TYPE_DEFINITION) continue;\n // Skip if an input type with the same name already exists in the schema\n // or in operation schemas (to avoid duplicates with moduleSchemas)\n const inputName = `${def.name.value}Input`;\n if (existingInputNames.has(inputName)) continue;\n if (excludeTypeNames?.has(inputName)) continue;\n const fields = def.fields ?? [];\n if (fields.length === 0) continue;\n\n const inputFields = fields.map((field) => {\n const fieldName = field.name.value;\n const fieldType = convertTypeNodeToInput(\n field.type as GraphQLTypeNode,\n objectNames,\n unionNames,\n interfaceNames,\n );\n return ` ${fieldName}: ${fieldType}`;\n });\n\n inputTypes.push(\n `input ${def.name.value}Input {\\n${inputFields.join(\"\\n\")}\\n}`,\n );\n }\n\n return inputTypes.join(\"\\n\\n\");\n}\n\n/**\n * Apply type prefixes to GraphQL schema to namespace types and avoid collisions.\n * Inlined from @powerhousedao/common/utils to avoid ES module import issues.\n * @param {string} schema - GraphQL schema string\n * @param {string} prefix - Prefix to apply to type names\n * @param {string[]} externalTypeNames - Type names from other schemas to also prefix\n * @returns {string} Schema with prefixed types\n */\nfunction applyGraphQLTypePrefixes(\n schema: string,\n prefix: string,\n externalTypeNames: string[] = [],\n): string {\n if (!schema || !schema.trim()) {\n return schema;\n }\n\n const doc = parseSdl(schema);\n const names = new Set([\n ...definedTypeNames(doc, ALL_PREFIX_KINDS),\n ...externalTypeNames,\n ]);\n if (names.size === 0) return schema;\n return print(prefixTypeNames(doc, prefix, names));\n}\n\n/**\n * Options for generating document model GraphQL schemas.\n */\nexport interface DocumentModelSchemaOptions {\n /**\n * When true, generates new API patterns:\n * - Mutations return full document objects (MutationResult type)\n * - Adds createEmptyDocument mutation\n * - Makes docId and input parameters required\n * @default false\n */\n useNewApi?: boolean;\n}\n\n/**\n * Generate a GraphQL schema for a document model.\n *\n * @param documentModel - The document model global state\n * @param options - Schema generation options\n * @returns GraphQL DocumentNode\n */\nexport function generateDocumentModelSchema(\n documentModel: DocumentModelGlobalState,\n options: DocumentModelSchemaOptions = {},\n): DocumentNode {\n const { useNewApi = false } = options;\n\n const specification = documentModel.specifications.at(-1);\n const documentName = getDocumentModelSchemaName(documentModel);\n const globalStateSchema = specification?.state.global.schema;\n const localStateSchema = specification?.state.local.schema;\n const globalStateTypeNames = extractTypeNames(globalStateSchema ?? \"\");\n const localStateTypeNames = extractTypeNames(localStateSchema ?? \"\");\n const stateTypeNames = [...globalStateTypeNames, ...localStateTypeNames];\n\n // Collect ALL type names from all operations' schemas\n const allOperationTypeNames =\n specification?.modules.flatMap((module) =>\n module.operations.flatMap((op) => extractTypeNames(op.schema ?? \"\")),\n ) ?? [];\n\n // Combine state types and all operation types for prefixing\n const allTypeNames = [\n ...new Set([...stateTypeNames, ...allOperationTypeNames]),\n ];\n\n // Extract input type definitions from state schema, excluding operation-specific inputs\n // (those are already defined in op.schema)\n const operationInputTypeNames = new Set(allOperationTypeNames);\n const stateInputTypes = extractInputTypeDefinitions(\n globalStateSchema ?? \"\",\n operationInputTypeNames,\n );\n const prefixedStateInputTypes = applyGraphQLTypePrefixes(\n stateInputTypes,\n documentName,\n allTypeNames,\n );\n\n // Helper to check if schema has actual GraphQL type definitions\n const hasValidSchema = (schema: string | null | undefined): boolean =>\n !!(schema && /\\b(input|type|enum|union|interface)\\s+\\w+/.test(schema));\n\n if (useNewApi) {\n // New API: flat queries, typed state, async mutations\n return generateNewApiSchema(\n documentName,\n specification,\n prefixedStateInputTypes,\n allTypeNames,\n hasValidSchema,\n );\n }\n\n // Legacy API\n return generateLegacyApiSchema(\n documentName,\n specification,\n prefixedStateInputTypes,\n allTypeNames,\n hasValidSchema,\n );\n}\n\n/**\n * Generate legacy API schema with nested queries\n */\nfunction generateLegacyApiSchema(\n documentName: string,\n specification: DocumentModelGlobalState[\"specifications\"][0] | undefined,\n prefixedStateInputTypes: string,\n allTypeNames: string[],\n hasValidSchema: (schema: string | null | undefined) => boolean,\n): DocumentNode {\n const createDocumentMutation = `${documentName}_createDocument(name:String!, driveId:String): String`;\n\n const operationMutations =\n specification?.modules\n .flatMap((module) =>\n module.operations\n .filter((op) => op.name && hasValidSchema(op.schema))\n .map(\n (op) =>\n `${documentName}_${camelCase(op.name!)}(\n driveId: String, docId: PHID, input: ${documentName}_${pascalCase(op.name!)}Input): Int`,\n ),\n )\n .join(\"\\n \") ?? \"\";\n\n const moduleSchemas = buildModuleSchemas(\n specification,\n documentName,\n allTypeNames,\n hasValidSchema,\n );\n\n return gql`\n \"\"\"\n Queries: ${documentName} Document\n \"\"\"\n\n type ${documentName}Queries {\n getDocument(docId: PHID!, driveId: PHID): ${documentName}\n getDocuments(driveId: String!): [${documentName}!]\n }\n\n type Query {\n ${documentName}: ${documentName}Queries\n }\n\n \"\"\"\n Mutations: ${documentName}\n \"\"\"\n type Mutation {\n ${createDocumentMutation}\n\n ${operationMutations}\n }\n\n ${\n prefixedStateInputTypes\n ? `\"\"\"\n Input Types from State Schema\n \"\"\"\n ${prefixedStateInputTypes}`\n : \"\"\n }\n\n ${moduleSchemas}`;\n}\n\n/**\n * Generate new API schema with flat queries, typed state, and async mutations.\n * Note: State schema types are NOT included here because they are already defined\n * in getDocumentModelTypeDefs() which is used during schema composition.\n * Including them here would cause duplicate type definitions.\n */\nfunction generateNewApiSchema(\n documentName: string,\n specification: DocumentModelGlobalState[\"specifications\"][0] | undefined,\n prefixedStateInputTypes: string,\n allTypeNames: string[],\n hasValidSchema: (schema: string | null | undefined) => boolean,\n): DocumentNode {\n // Use full state type for all document models\n const stateType = `${documentName}_FullState!`;\n\n // Shared base types for document state structure (same for all document types)\n const sharedBaseTypes = `\n \"\"\"Hash configuration for document state\"\"\"\n type ${documentName}_PHHashConfig {\n algorithm: String!\n encoding: String!\n }\n\n \"\"\"Document scope state (same for all document types)\"\"\"\n type ${documentName}_PHDocumentScopeState {\n version: Int!\n hash: ${documentName}_PHHashConfig!\n isDeleted: Boolean\n deletedAtUtcIso: String\n deletedBy: String\n deletionReason: String\n }\n `;\n\n // Full state type with all scopes (auth, document, global, local)\n // Note: DocumentModel uses different naming convention (GlobalState suffix instead of State)\n // For local state, check if the specification defines a local state type\n const localSchema = specification?.state.local.schema ?? \"\";\n const hasLocalStateType = localSchema.includes(\n `type ${documentName}LocalState`,\n );\n\n const globalStateType =\n documentName === \"DocumentModel\"\n ? `${documentName}_${documentName}GlobalState!`\n : `${documentName}_${documentName}State!`;\n const localStateType = !hasLocalStateType\n ? \"JSONObject!\"\n : `${documentName}_${documentName}LocalState!`;\n\n const fullStateType = `\n \"\"\"Full state with all scopes for ${documentName}\"\"\"\n type ${documentName}_FullState {\n auth: JSONObject!\n document: ${documentName}_PHDocumentScopeState!\n global: ${globalStateType}\n local: ${localStateType}\n }\n `;\n\n // Common input types - use extend to avoid conflicts with other subgraphs\n const commonInputTypes = `\n input ${documentName}_ViewFilterInput {\n branch: String\n scopes: [String!]\n }\n\n input ${documentName}_PagingInput {\n limit: Int\n offset: Int\n cursor: String\n }\n\n input ${documentName}_SearchFilterInput {\n parentId: String\n identifiers: [String!]\n }\n `;\n\n // Revision type - imported from shared-schema.ts for consistency with ReactorSubgraph\n // Must be defined in each subgraph for Apollo Federation\n const revisionType = RevisionType;\n\n // Result types with typed state (or JSONObject for DocumentModel)\n // The state type (${documentName}_${documentName}State) is defined in getDocumentModelTypeDefs()\n // Uses revisionsList with shared Revision type to match ReactorSubgraph pattern\n const resultTypes = `\n \"\"\"\n Mutation result type for ${documentName} operations with typed state.\n Matches ReactorSubgraph PHDocument pattern with revisionsList.\n \"\"\"\n type ${documentName}MutationResult {\n id: String!\n slug: String\n preferredEditor: String\n name: String!\n documentType: String!\n state: ${stateType}\n revisionsList: [Revision!]!\n createdAtUtcIso: DateTime!\n lastModifiedAtUtcIso: DateTime!\n }\n\n \"\"\"\n Document with children for ${documentName}\n \"\"\"\n type ${documentName}_DocumentWithChildren {\n document: ${documentName}MutationResult!\n childIds: [String!]!\n }\n\n \"\"\"\n Paginated result type for ${documentName} documents\n \"\"\"\n type ${documentName}_DocumentResultPage {\n items: [${documentName}MutationResult!]!\n hasNextPage: Boolean!\n hasPreviousPage: Boolean!\n cursor: String\n }\n `;\n\n // Queries nested under ${documentName} namespace\n const queries = `\n type ${documentName}Queries {\n \"\"\"Get a specific ${documentName} document by identifier\"\"\"\n document(identifier: String!, view: ${documentName}_ViewFilterInput): ${documentName}_DocumentWithChildren\n\n \"\"\"Get all ${documentName} documents (paged)\"\"\"\n documents(paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!\n\n \"\"\"Find ${documentName} documents by search criteria\"\"\"\n findDocuments(search: ${documentName}_SearchFilterInput, view: ${documentName}_ViewFilterInput, paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!\n\n \"\"\"Get outgoing relationships of a ${documentName} document\"\"\"\n documentOutgoingRelationships(sourceIdentifier: String!, relationshipType: String!, view: ${documentName}_ViewFilterInput, paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!\n\n \"\"\"Get incoming relationships to a ${documentName} document\"\"\"\n documentIncomingRelationships(targetIdentifier: String!, relationshipType: String!, view: ${documentName}_ViewFilterInput, paging: ${documentName}_PagingInput): ${documentName}_DocumentResultPage!\n }\n `;\n\n // Generate initial state input types for each scope\n let initialStateInputSchema = \"\";\n if (specification) {\n const scopeFields: string[] = [];\n const generatedInputTypeParts: string[] = [];\n\n for (const [scopeName, scopeState] of Object.entries(specification.state)) {\n const schema = (scopeState as { schema?: string }).schema ?? \"\";\n if (hasValidSchema(schema)) {\n const rootTypeName = extractRootTypeName(\n schema,\n documentName,\n scopeName,\n );\n if (!rootTypeName) {\n scopeFields.push(` ${scopeName}: JSONObject`);\n continue;\n }\n const scopeInputTypes = generateStateInputTypes(\n schema,\n new Set(allTypeNames),\n );\n if (!scopeInputTypes) {\n scopeFields.push(` ${scopeName}: JSONObject`);\n continue;\n }\n const prefixedScopeInputTypes = applyGraphQLTypePrefixes(\n scopeInputTypes,\n documentName,\n allTypeNames,\n );\n scopeFields.push(\n ` ${scopeName}: ${documentName}_${rootTypeName}Input`,\n );\n generatedInputTypeParts.push(prefixedScopeInputTypes);\n } else {\n scopeFields.push(` ${scopeName}: JSONObject`);\n }\n }\n\n if (scopeFields.length > 0) {\n const inputTypeDefs = generatedInputTypeParts.join(\"\\n\\n\");\n const wrapper = `input ${documentName}_InitialStateInput {\\n${scopeFields.join(\"\\n\")}\\n}`;\n initialStateInputSchema = inputTypeDefs\n ? `${inputTypeDefs}\\n\\n${wrapper}`\n : wrapper;\n }\n }\n\n // Mutations nested under ${documentName} namespace\n const createDocumentMutation = initialStateInputSchema\n ? `createDocument(name: String!, parentIdentifier: String, slug: String, preferredEditor: String, initialState: ${documentName}_InitialStateInput): ${documentName}MutationResult!`\n : `createDocument(name: String!, parentIdentifier: String, preferredEditor: String): ${documentName}MutationResult!`;\n const createEmptyDocumentMutation = `createEmptyDocument(parentIdentifier: String): ${documentName}MutationResult!`;\n\n const operationMutations =\n specification?.modules\n .flatMap((module) =>\n module.operations\n .filter((op) => op.name && hasValidSchema(op.schema))\n .flatMap((op) => [\n // Sync mutation\n `${camelCase(op.name!)}(docId: PHID!, input: ${documentName}_${pascalCase(op.name!)}Input!): ${documentName}MutationResult!`,\n // Async mutation\n `${camelCase(op.name!)}Async(docId: PHID!, input: ${documentName}_${pascalCase(op.name!)}Input!): String!`,\n ]),\n )\n .join(\"\\n \") ?? \"\";\n\n const moduleSchemas = buildModuleSchemas(\n specification,\n documentName,\n allTypeNames,\n hasValidSchema,\n );\n\n return gql`\n scalar DateTime\n scalar JSONObject\n scalar AttachmentRef\n\n ${revisionType}\n\n ${sharedBaseTypes}\n\n ${fullStateType}\n\n ${commonInputTypes}\n\n ${resultTypes}\n\n \"\"\"\n Queries: ${documentName} Document\n \"\"\"\n ${queries}\n\n \"\"\"\n Mutations: ${documentName}\n \"\"\"\n type ${documentName}Mutations {\n ${createDocumentMutation}\n ${createEmptyDocumentMutation}\n\n ${operationMutations}\n }\n\n type Query {\n ${documentName}: ${documentName}Queries!\n }\n\n type Mutation {\n ${documentName}: ${documentName}Mutations!\n }\n\n ${\n prefixedStateInputTypes\n ? `\"\"\"\n Input Types from State Schema\n \"\"\"\n ${prefixedStateInputTypes}`\n : \"\"\n }\n\n ${\n initialStateInputSchema\n ? `\"\"\"\n Input Types for Initial State\n \"\"\"\n ${initialStateInputSchema}`\n : \"\"\n }\n\n ${moduleSchemas}`;\n}\n","import type {\n GraphQLResolveInfo,\n GraphQLScalarType,\n GraphQLScalarTypeConfig,\n} from \"graphql\";\nimport type { Context } from \"../../types.js\";\nimport * as z from \"zod\";\nimport type { DocumentNode } from \"graphql\";\nimport { gql } from \"graphql-tag\";\nexport type Maybe<T> = T | null | undefined;\nexport type InputMaybe<T> = T | null | undefined;\nexport type Exact<T extends { [key: string]: unknown }> = {\n [K in keyof T]: T[K];\n};\nexport type MakeOptional<T, K extends keyof T> = Omit<T, K> & {\n [SubKey in K]?: Maybe<T[SubKey]>;\n};\nexport type MakeMaybe<T, K extends keyof T> = Omit<T, K> & {\n [SubKey in K]: Maybe<T[SubKey]>;\n};\nexport type MakeEmpty<\n T extends { [key: string]: unknown },\n K extends keyof T,\n> = { [_ in K]?: never };\nexport type Incremental<T> =\n | T\n | {\n [P in keyof T]?: P extends \" $fragmentName\" | \"__typename\" ? T[P] : never;\n };\nexport type RequireFields<T, K extends keyof T> = Omit<T, K> & {\n [P in K]-?: NonNullable<T[P]>;\n};\n/** All built-in and custom scalars, mapped to their actual values */\nexport type Scalars = {\n ID: { input: string; output: string };\n String: { input: string; output: string };\n Boolean: { input: boolean; output: boolean };\n Int: { input: number; output: number };\n Float: { input: number; output: number };\n DateTime: { input: string | Date; output: string | Date };\n JSONObject: { input: NonNullable<unknown>; output: NonNullable<unknown> };\n};\n\nexport type Action = {\n readonly context?: Maybe<ActionContext>;\n readonly id: Scalars[\"String\"][\"output\"];\n readonly input: Scalars[\"JSONObject\"][\"output\"];\n readonly scope: Scalars[\"String\"][\"output\"];\n readonly timestampUtcMs: Scalars[\"String\"][\"output\"];\n readonly type: Scalars[\"String\"][\"output\"];\n};\n\n/**\n * One operation an authorization preflight predicts a verdict for.\n *\n * `input` is what a conditional grant reads, so a candidate standing for a\n * filled-in form carries that form's input. Omitting it predicts the verdict an\n * empty input earns, not the verdict the filled-in form will get.\n */\nexport type ActionCandidateInput = {\n readonly input?: InputMaybe<Scalars[\"JSONObject\"][\"input\"]>;\n readonly scope: Scalars[\"String\"][\"input\"];\n readonly type: Scalars[\"String\"][\"input\"];\n};\n\nexport type ActionContext = {\n readonly signer?: Maybe<ReactorSigner>;\n};\n\n/**\n * An action's context, as a caller submits it.\n *\n * Declares every field `ActionContext` carries, because an input object rejects a\n * field it does not declare: an action stamped with the head it applies to - which\n * is what a signing client sends - is refused outright if these are missing, and\n * that refusal is a whole-request one, not a per-field one.\n *\n * `prevOpHash` and `prevOpIndex` are the scope head the action was composed\n * against. They are recorded rather than enforced; a signature is verified from\n * the params carried in its own tuple, which do not include them.\n */\nexport type ActionContextInput = {\n /** Covers replay of an operation that would otherwise be a no-op. */\n readonly nonce?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n /** The hash of the state the action applies to. */\n readonly prevOpHash?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n /** The index of the last operation in the scope the action applies to. */\n readonly prevOpIndex?: InputMaybe<Scalars[\"Int\"][\"input\"]>;\n readonly signer?: InputMaybe<ReactorSignerInput>;\n};\n\n/**\n * One candidate's predicted verdict. `reason` carries the refusal a DENY is\n * recorded with, and is null on an ALLOW.\n */\nexport type ActionEvaluation = {\n readonly decision: AuthDecision;\n readonly reason?: Maybe<Scalars[\"String\"][\"output\"]>;\n};\n\n/**\n * The predicted verdicts for a set of candidates, in the order they were given,\n * with the aggregates a caller branches on.\n *\n * The aggregates are redundant -- a verdict is binary -- and all four are returned\n * so a caller reads the one its question is phrased in rather than negating\n * another. Over no candidates every aggregate is false: nothing is allowed and\n * nothing is denied.\n */\nexport type ActionEvaluations = {\n readonly allAllowed: Scalars[\"Boolean\"][\"output\"];\n readonly allDenied: Scalars[\"Boolean\"][\"output\"];\n readonly anyAllowed: Scalars[\"Boolean\"][\"output\"];\n readonly anyDenied: Scalars[\"Boolean\"][\"output\"];\n readonly evaluations: ReadonlyArray<ActionEvaluation>;\n};\n\nexport type ActionInput = {\n readonly context?: InputMaybe<ActionContextInput>;\n readonly id: Scalars[\"String\"][\"input\"];\n readonly input: Scalars[\"JSONObject\"][\"input\"];\n readonly scope: Scalars[\"String\"][\"input\"];\n readonly timestampUtcMs: Scalars[\"String\"][\"input\"];\n readonly type: Scalars[\"String\"][\"input\"];\n};\n\nexport enum AuthDecision {\n Allow = \"ALLOW\",\n Deny = \"DENY\",\n}\n\nexport type ChannelMeta = {\n readonly id: Scalars[\"String\"][\"output\"];\n};\n\nexport type ChannelMetaInput = {\n readonly id: Scalars[\"String\"][\"input\"];\n};\n\nexport type DeadLetterInfo = {\n readonly branch: Scalars[\"String\"][\"output\"];\n readonly documentId: Scalars[\"String\"][\"output\"];\n readonly error: Scalars[\"String\"][\"output\"];\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 readonly errorType?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly jobId: Scalars[\"String\"][\"output\"];\n readonly operationCount: Scalars[\"Int\"][\"output\"];\n readonly scopes: ReadonlyArray<Scalars[\"String\"][\"output\"]>;\n};\n\nexport type DocumentChangeContext = {\n readonly childId?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly parentId?: Maybe<Scalars[\"String\"][\"output\"]>;\n};\n\nexport type DocumentChangeEvent = {\n readonly context?: Maybe<DocumentChangeContext>;\n readonly documents: ReadonlyArray<PhDocument>;\n readonly type: DocumentChangeType;\n};\n\nexport enum DocumentChangeType {\n ChildAdded = \"CHILD_ADDED\",\n ChildRemoved = \"CHILD_REMOVED\",\n Created = \"CREATED\",\n Deleted = \"DELETED\",\n ParentAdded = \"PARENT_ADDED\",\n ParentRemoved = \"PARENT_REMOVED\",\n Updated = \"UPDATED\",\n}\n\nexport type DocumentModelGlobalState = {\n readonly id: Scalars[\"String\"][\"output\"];\n readonly name: Scalars[\"String\"][\"output\"];\n readonly namespace?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly specification: Scalars[\"JSONObject\"][\"output\"];\n readonly version?: Maybe<Scalars[\"String\"][\"output\"]>;\n};\n\nexport type DocumentModelResultPage = {\n readonly cursor?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly hasNextPage: Scalars[\"Boolean\"][\"output\"];\n readonly hasPreviousPage: Scalars[\"Boolean\"][\"output\"];\n readonly items: ReadonlyArray<DocumentModelGlobalState>;\n};\n\nexport type DocumentOperationsFilterInput = {\n readonly actionTypes?: InputMaybe<ReadonlyArray<Scalars[\"String\"][\"input\"]>>;\n readonly branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly scopes?: InputMaybe<ReadonlyArray<Scalars[\"String\"][\"input\"]>>;\n readonly sinceRevision?: InputMaybe<Scalars[\"Int\"][\"input\"]>;\n readonly timestampFrom?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly timestampTo?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n};\n\nexport type DocumentRelationship = {\n readonly createdAt: Scalars[\"DateTime\"][\"output\"];\n readonly metadata?: Maybe<Scalars[\"JSONObject\"][\"output\"]>;\n readonly relationshipType: Scalars[\"String\"][\"output\"];\n readonly sourceId: Scalars[\"String\"][\"output\"];\n readonly targetId: Scalars[\"String\"][\"output\"];\n readonly updatedAt: Scalars[\"DateTime\"][\"output\"];\n};\n\nexport type DocumentRelationshipResultPage = {\n readonly cursor?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly hasNextPage: Scalars[\"Boolean\"][\"output\"];\n readonly hasPreviousPage: Scalars[\"Boolean\"][\"output\"];\n readonly items: ReadonlyArray<DocumentRelationship>;\n};\n\nexport type DocumentWithChildren = {\n readonly childIds: ReadonlyArray<Scalars[\"String\"][\"output\"]>;\n readonly document: PhDocument;\n};\n\nexport type JobChangeEvent = {\n readonly error?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly jobId: Scalars[\"String\"][\"output\"];\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 readonly result?: Maybe<Scalars[\"JSONObject\"][\"output\"]>;\n readonly status: Scalars[\"String\"][\"output\"];\n};\n\nexport type JobInfo = {\n readonly completedAt?: Maybe<Scalars[\"DateTime\"][\"output\"]>;\n readonly createdAt: Scalars[\"DateTime\"][\"output\"];\n readonly error?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly id: Scalars[\"String\"][\"output\"];\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 readonly result?: Maybe<Scalars[\"JSONObject\"][\"output\"]>;\n readonly status: Scalars[\"String\"][\"output\"];\n};\n\nexport type MoveRelationshipResult = {\n readonly source: PhDocument;\n readonly target: PhDocument;\n};\n\nexport type Mutation = {\n readonly addRelationship: PhDocument;\n readonly createDocument: PhDocument;\n readonly createEmptyDocument: PhDocument;\n readonly deleteDocument: Scalars[\"Boolean\"][\"output\"];\n readonly deleteDocuments: Scalars[\"Boolean\"][\"output\"];\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 readonly execute: PhDocument;\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 readonly executeAsync: JobInfo;\n readonly moveRelationship: MoveRelationshipResult;\n /** @deprecated 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 readonly mutateDocument: PhDocument;\n /** @deprecated Use executeAsync, which is typed and returns the job rather than only its id. */\n readonly mutateDocumentAsync: Scalars[\"String\"][\"output\"];\n readonly pushSyncEnvelopes: Scalars[\"Boolean\"][\"output\"];\n readonly removeRelationship: PhDocument;\n readonly renameDocument: PhDocument;\n readonly setPreferredEditor: PhDocument;\n readonly touchChannel: TouchChannelResult;\n readonly updateRelationship: PhDocument;\n};\n\nexport type MutationAddRelationshipArgs = {\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n metadata?: InputMaybe<Scalars[\"JSONObject\"][\"input\"]>;\n relationshipType: Scalars[\"String\"][\"input\"];\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n};\n\nexport type MutationCreateDocumentArgs = {\n document: Scalars[\"JSONObject\"][\"input\"];\n parentIdentifier?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n};\n\nexport type MutationCreateEmptyDocumentArgs = {\n documentType: Scalars[\"String\"][\"input\"];\n parentIdentifier?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n};\n\nexport type MutationDeleteDocumentArgs = {\n identifier: Scalars[\"String\"][\"input\"];\n propagate?: InputMaybe<PropagationMode>;\n};\n\nexport type MutationDeleteDocumentsArgs = {\n identifiers: ReadonlyArray<Scalars[\"String\"][\"input\"]>;\n propagate?: InputMaybe<PropagationMode>;\n};\n\nexport type MutationExecuteArgs = {\n actions: ReadonlyArray<ActionInput>;\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n documentIdentifier: Scalars[\"String\"][\"input\"];\n};\n\nexport type MutationExecuteAsyncArgs = {\n actions: ReadonlyArray<ActionInput>;\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n documentIdentifier: Scalars[\"String\"][\"input\"];\n};\n\nexport type MutationMoveRelationshipArgs = {\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n relationshipType: Scalars[\"String\"][\"input\"];\n sourceParentIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n targetParentIdentifier: Scalars[\"String\"][\"input\"];\n};\n\nexport type MutationMutateDocumentArgs = {\n actions: ReadonlyArray<Scalars[\"JSONObject\"][\"input\"]>;\n documentIdentifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type MutationMutateDocumentAsyncArgs = {\n actions: ReadonlyArray<Scalars[\"JSONObject\"][\"input\"]>;\n documentIdentifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type MutationPushSyncEnvelopesArgs = {\n envelopes: ReadonlyArray<SyncEnvelopeInput>;\n};\n\nexport type MutationRemoveRelationshipArgs = {\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n relationshipType: Scalars[\"String\"][\"input\"];\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n};\n\nexport type MutationRenameDocumentArgs = {\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n documentIdentifier: Scalars[\"String\"][\"input\"];\n name: Scalars[\"String\"][\"input\"];\n};\n\nexport type MutationSetPreferredEditorArgs = {\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n documentIdentifier: Scalars[\"String\"][\"input\"];\n preferredEditor?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n};\n\nexport type MutationTouchChannelArgs = {\n input: TouchChannelInput;\n};\n\nexport type MutationUpdateRelationshipArgs = {\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n metadata?: InputMaybe<Scalars[\"JSONObject\"][\"input\"]>;\n relationshipType: Scalars[\"String\"][\"input\"];\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n};\n\nexport type OperationContext = {\n readonly branch: Scalars[\"String\"][\"output\"];\n readonly documentId: Scalars[\"String\"][\"output\"];\n readonly documentType: Scalars[\"String\"][\"output\"];\n readonly ordinal: Scalars[\"Int\"][\"output\"];\n readonly scope: Scalars[\"String\"][\"output\"];\n};\n\nexport type OperationContextInput = {\n readonly branch: Scalars[\"String\"][\"input\"];\n readonly documentId: Scalars[\"String\"][\"input\"];\n readonly documentType: Scalars[\"String\"][\"input\"];\n readonly ordinal: Scalars[\"Int\"][\"input\"];\n readonly scope: Scalars[\"String\"][\"input\"];\n};\n\nexport type OperationInput = {\n readonly action: ActionInput;\n readonly deniedReason?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly error?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly hash: Scalars[\"String\"][\"input\"];\n readonly id?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly index: Scalars[\"Int\"][\"input\"];\n readonly skip: Scalars[\"Int\"][\"input\"];\n readonly timestampUtcMs: Scalars[\"String\"][\"input\"];\n};\n\nexport type OperationWithContext = {\n readonly context: OperationContext;\n readonly operation: ReactorOperation;\n};\n\nexport type OperationWithContextInput = {\n readonly context: OperationContextInput;\n readonly operation: OperationInput;\n};\n\nexport type OperationsFilterInput = {\n readonly actionTypes?: InputMaybe<ReadonlyArray<Scalars[\"String\"][\"input\"]>>;\n readonly branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly documentId: Scalars[\"String\"][\"input\"];\n readonly scopes?: InputMaybe<ReadonlyArray<Scalars[\"String\"][\"input\"]>>;\n readonly sinceRevision?: InputMaybe<Scalars[\"Int\"][\"input\"]>;\n readonly timestampFrom?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly timestampTo?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n};\n\nexport type PhDocument = {\n readonly createdAtUtcIso: Scalars[\"DateTime\"][\"output\"];\n readonly documentType: Scalars[\"String\"][\"output\"];\n readonly id: Scalars[\"String\"][\"output\"];\n readonly lastModifiedAtUtcIso: Scalars[\"DateTime\"][\"output\"];\n readonly name: Scalars[\"String\"][\"output\"];\n readonly operations?: Maybe<ReactorOperationResultPage>;\n readonly preferredEditor?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly revisionsList: ReadonlyArray<Revision>;\n readonly slug?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly state: Scalars[\"JSONObject\"][\"output\"];\n};\n\nexport type PhDocumentOperationsArgs = {\n filter?: InputMaybe<DocumentOperationsFilterInput>;\n paging?: InputMaybe<PagingInput>;\n};\n\nexport type PhDocumentResultPage = {\n readonly cursor?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly hasNextPage: Scalars[\"Boolean\"][\"output\"];\n readonly hasPreviousPage: Scalars[\"Boolean\"][\"output\"];\n readonly items: ReadonlyArray<PhDocument>;\n};\n\nexport type PagingInput = {\n readonly cursor?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly limit?: InputMaybe<Scalars[\"Int\"][\"input\"]>;\n readonly offset?: InputMaybe<Scalars[\"Int\"][\"input\"]>;\n};\n\nexport type PollSyncEnvelopesResult = {\n readonly ackOrdinal: Scalars[\"Int\"][\"output\"];\n readonly deadLetters: ReadonlyArray<DeadLetterInfo>;\n readonly envelopes: ReadonlyArray<SyncEnvelope>;\n readonly hasMore: Scalars[\"Boolean\"][\"output\"];\n};\n\nexport enum PropagationMode {\n Cascade = \"CASCADE\",\n Orphan = \"ORPHAN\",\n}\n\nexport type Query = {\n readonly document?: Maybe<DocumentWithChildren>;\n readonly documentIncomingRelationshipEdges: DocumentRelationshipResultPage;\n readonly documentIncomingRelationships: PhDocumentResultPage;\n readonly documentModels: DocumentModelResultPage;\n readonly documentOperations: ReactorOperationResultPage;\n readonly documentOutgoingRelationshipEdges: DocumentRelationshipResultPage;\n readonly documentOutgoingRelationships: PhDocumentResultPage;\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 readonly evaluateActions: ActionEvaluations;\n readonly findDocuments: PhDocumentResultPage;\n readonly jobStatus?: Maybe<JobInfo>;\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 readonly pollSyncEnvelopes: PollSyncEnvelopesResult;\n};\n\nexport type QueryDocumentArgs = {\n identifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type QueryDocumentIncomingRelationshipEdgesArgs = {\n paging?: InputMaybe<PagingInput>;\n relationshipType?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n targetIdentifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type QueryDocumentIncomingRelationshipsArgs = {\n paging?: InputMaybe<PagingInput>;\n relationshipType: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type QueryDocumentModelsArgs = {\n namespace?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n paging?: InputMaybe<PagingInput>;\n};\n\nexport type QueryDocumentOperationsArgs = {\n filter: OperationsFilterInput;\n paging?: InputMaybe<PagingInput>;\n};\n\nexport type QueryDocumentOutgoingRelationshipEdgesArgs = {\n paging?: InputMaybe<PagingInput>;\n relationshipType?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type QueryDocumentOutgoingRelationshipsArgs = {\n paging?: InputMaybe<PagingInput>;\n relationshipType: Scalars[\"String\"][\"input\"];\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type QueryEvaluateActionsArgs = {\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n candidates: ReadonlyArray<ActionCandidateInput>;\n documentIdentifier: Scalars[\"String\"][\"input\"];\n};\n\nexport type QueryFindDocumentsArgs = {\n paging?: InputMaybe<PagingInput>;\n search?: InputMaybe<SearchFilterInput>;\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type QueryJobStatusArgs = {\n jobId: Scalars[\"String\"][\"input\"];\n};\n\nexport type QueryPollSyncEnvelopesArgs = {\n channelId: Scalars[\"String\"][\"input\"];\n outboxAck: Scalars[\"Int\"][\"input\"];\n outboxLatest: Scalars[\"Int\"][\"input\"];\n};\n\nexport type ReactorOperation = {\n readonly action: Action;\n readonly deniedReason?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly error?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly hash: Scalars[\"String\"][\"output\"];\n readonly id?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly index: Scalars[\"Int\"][\"output\"];\n readonly skip: Scalars[\"Int\"][\"output\"];\n readonly timestampUtcMs: Scalars[\"String\"][\"output\"];\n};\n\nexport type ReactorOperationResultPage = {\n readonly cursor?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly hasNextPage: Scalars[\"Boolean\"][\"output\"];\n readonly hasPreviousPage: Scalars[\"Boolean\"][\"output\"];\n readonly items: ReadonlyArray<ReactorOperation>;\n};\n\nexport type ReactorSigner = {\n readonly app?: Maybe<ReactorSignerApp>;\n readonly signatures: ReadonlyArray<Scalars[\"String\"][\"output\"]>;\n readonly user?: Maybe<ReactorSignerUser>;\n};\n\nexport type ReactorSignerApp = {\n readonly key: Scalars[\"String\"][\"output\"];\n readonly name: Scalars[\"String\"][\"output\"];\n};\n\nexport type ReactorSignerAppInput = {\n readonly key: Scalars[\"String\"][\"input\"];\n readonly name: Scalars[\"String\"][\"input\"];\n};\n\nexport type ReactorSignerInput = {\n readonly app?: InputMaybe<ReactorSignerAppInput>;\n readonly signatures: ReadonlyArray<Scalars[\"String\"][\"input\"]>;\n readonly user?: InputMaybe<ReactorSignerUserInput>;\n};\n\nexport type ReactorSignerUser = {\n readonly address: Scalars[\"String\"][\"output\"];\n readonly chainId: Scalars[\"Int\"][\"output\"];\n readonly networkId: Scalars[\"String\"][\"output\"];\n};\n\nexport type ReactorSignerUserInput = {\n readonly address: Scalars[\"String\"][\"input\"];\n readonly chainId: Scalars[\"Int\"][\"input\"];\n readonly networkId: Scalars[\"String\"][\"input\"];\n};\n\nexport type RemoteCursor = {\n readonly cursorOrdinal: Scalars[\"Int\"][\"output\"];\n readonly lastSyncedAtUtcMs?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly remoteName: Scalars[\"String\"][\"output\"];\n};\n\nexport type RemoteCursorInput = {\n readonly cursorOrdinal: Scalars[\"Int\"][\"input\"];\n readonly lastSyncedAtUtcMs?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly remoteName: Scalars[\"String\"][\"input\"];\n};\n\nexport type RemoteFilterInput = {\n readonly branch: Scalars[\"String\"][\"input\"];\n readonly documentId: ReadonlyArray<Scalars[\"String\"][\"input\"]>;\n readonly scope: ReadonlyArray<Scalars[\"String\"][\"input\"]>;\n};\n\nexport type Revision = {\n readonly revision: Scalars[\"Int\"][\"output\"];\n readonly scope: Scalars[\"String\"][\"output\"];\n};\n\nexport type SearchFilterInput = {\n readonly identifiers?: InputMaybe<ReadonlyArray<Scalars[\"String\"][\"input\"]>>;\n readonly parentId?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly type?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n};\n\nexport type Subscription = {\n readonly documentChanges: DocumentChangeEvent;\n readonly jobChanges: JobChangeEvent;\n};\n\nexport type SubscriptionDocumentChangesArgs = {\n search?: InputMaybe<SearchFilterInput>;\n view?: InputMaybe<ViewFilterInput>;\n};\n\nexport type SubscriptionJobChangesArgs = {\n jobId: Scalars[\"String\"][\"input\"];\n};\n\nexport type SyncEnvelope = {\n readonly channelMeta: ChannelMeta;\n readonly cursor?: Maybe<RemoteCursor>;\n readonly dependsOn?: Maybe<ReadonlyArray<Scalars[\"String\"][\"output\"]>>;\n readonly key?: Maybe<Scalars[\"String\"][\"output\"]>;\n readonly operations?: Maybe<ReadonlyArray<OperationWithContext>>;\n readonly type: SyncEnvelopeType;\n};\n\nexport type SyncEnvelopeInput = {\n readonly channelMeta: ChannelMetaInput;\n readonly cursor?: InputMaybe<RemoteCursorInput>;\n readonly dependsOn?: InputMaybe<ReadonlyArray<Scalars[\"String\"][\"input\"]>>;\n readonly key?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly operations?: InputMaybe<ReadonlyArray<OperationWithContextInput>>;\n readonly type: SyncEnvelopeType;\n};\n\nexport enum SyncEnvelopeType {\n Ack = \"ACK\",\n Operations = \"OPERATIONS\",\n}\n\nexport type TouchChannelInput = {\n readonly collectionId: Scalars[\"String\"][\"input\"];\n readonly filter: RemoteFilterInput;\n readonly id: Scalars[\"String\"][\"input\"];\n readonly name: Scalars[\"String\"][\"input\"];\n readonly sinceTimestampUtcMs: Scalars[\"String\"][\"input\"];\n};\n\nexport type TouchChannelResult = {\n readonly ackOrdinal: Scalars[\"Int\"][\"output\"];\n readonly success: Scalars[\"Boolean\"][\"output\"];\n};\n\nexport type ViewFilterInput = {\n readonly branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n readonly scopes?: InputMaybe<ReadonlyArray<Scalars[\"String\"][\"input\"]>>;\n};\n\nexport type PhDocumentFieldsFragment = {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n};\n\nexport type DocumentRelationshipFieldsFragment = {\n readonly sourceId: string;\n readonly targetId: string;\n readonly relationshipType: string;\n readonly metadata?: NonNullable<unknown> | null | undefined;\n readonly createdAt: string | Date;\n readonly updatedAt: string | Date;\n};\n\nexport type GetDocumentModelsQueryVariables = Exact<{\n namespace?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n paging?: InputMaybe<PagingInput>;\n}>;\n\nexport type GetDocumentModelsQuery = {\n readonly documentModels: {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly id: string;\n readonly name: string;\n readonly namespace?: string | null | undefined;\n readonly version?: string | null | undefined;\n readonly specification: NonNullable<unknown>;\n }>;\n };\n};\n\nexport type GetDocumentQueryVariables = Exact<{\n identifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n}>;\n\nexport type GetDocumentQuery = {\n readonly document?:\n | {\n readonly childIds: ReadonlyArray<string>;\n readonly document: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n }\n | null\n | undefined;\n};\n\nexport type GetDocumentWithOperationsQueryVariables = Exact<{\n identifier: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n operationsFilter?: InputMaybe<DocumentOperationsFilterInput>;\n operationsPaging?: InputMaybe<PagingInput>;\n}>;\n\nexport type GetDocumentWithOperationsQuery = {\n readonly document?:\n | {\n readonly childIds: ReadonlyArray<string>;\n readonly document: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly operations?:\n | {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly index: number;\n readonly timestampUtcMs: string;\n readonly hash: string;\n readonly skip: number;\n readonly error?: string | null | undefined;\n readonly deniedReason?: string | null | undefined;\n readonly id?: string | null | undefined;\n readonly action: {\n readonly id: string;\n readonly type: string;\n readonly timestampUtcMs: string;\n readonly input: NonNullable<unknown>;\n readonly scope: string;\n readonly context?:\n | {\n readonly signer?:\n | {\n readonly signatures: ReadonlyArray<string>;\n readonly user?:\n | {\n readonly address: string;\n readonly networkId: string;\n readonly chainId: number;\n }\n | null\n | undefined;\n readonly app?:\n | {\n readonly name: string;\n readonly key: string;\n }\n | null\n | undefined;\n }\n | null\n | undefined;\n }\n | null\n | undefined;\n };\n }>;\n }\n | null\n | undefined;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n }\n | null\n | undefined;\n};\n\nexport type GetDocumentOutgoingRelationshipsQueryVariables = Exact<{\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n paging?: InputMaybe<PagingInput>;\n}>;\n\nexport type GetDocumentOutgoingRelationshipsQuery = {\n readonly documentOutgoingRelationships: {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n }>;\n };\n};\n\nexport type GetDocumentIncomingRelationshipsQueryVariables = Exact<{\n targetIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType: Scalars[\"String\"][\"input\"];\n view?: InputMaybe<ViewFilterInput>;\n paging?: InputMaybe<PagingInput>;\n}>;\n\nexport type GetDocumentIncomingRelationshipsQuery = {\n readonly documentIncomingRelationships: {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n }>;\n };\n};\n\nexport type GetDocumentOutgoingRelationshipEdgesQueryVariables = Exact<{\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n view?: InputMaybe<ViewFilterInput>;\n paging?: InputMaybe<PagingInput>;\n}>;\n\nexport type GetDocumentOutgoingRelationshipEdgesQuery = {\n readonly documentOutgoingRelationshipEdges: {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly sourceId: string;\n readonly targetId: string;\n readonly relationshipType: string;\n readonly metadata?: NonNullable<unknown> | null | undefined;\n readonly createdAt: string | Date;\n readonly updatedAt: string | Date;\n }>;\n };\n};\n\nexport type GetDocumentIncomingRelationshipEdgesQueryVariables = Exact<{\n targetIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n view?: InputMaybe<ViewFilterInput>;\n paging?: InputMaybe<PagingInput>;\n}>;\n\nexport type GetDocumentIncomingRelationshipEdgesQuery = {\n readonly documentIncomingRelationshipEdges: {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly sourceId: string;\n readonly targetId: string;\n readonly relationshipType: string;\n readonly metadata?: NonNullable<unknown> | null | undefined;\n readonly createdAt: string | Date;\n readonly updatedAt: string | Date;\n }>;\n };\n};\n\nexport type FindDocumentsQueryVariables = Exact<{\n search?: InputMaybe<SearchFilterInput>;\n view?: InputMaybe<ViewFilterInput>;\n paging?: InputMaybe<PagingInput>;\n}>;\n\nexport type FindDocumentsQuery = {\n readonly findDocuments: {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n }>;\n };\n};\n\nexport type GetDocumentOperationsQueryVariables = Exact<{\n filter: OperationsFilterInput;\n paging?: InputMaybe<PagingInput>;\n}>;\n\nexport type GetDocumentOperationsQuery = {\n readonly documentOperations: {\n readonly hasNextPage: boolean;\n readonly hasPreviousPage: boolean;\n readonly cursor?: string | null | undefined;\n readonly items: ReadonlyArray<{\n readonly index: number;\n readonly timestampUtcMs: string;\n readonly hash: string;\n readonly skip: number;\n readonly error?: string | null | undefined;\n readonly deniedReason?: string | null | undefined;\n readonly id?: string | null | undefined;\n readonly action: {\n readonly id: string;\n readonly type: string;\n readonly timestampUtcMs: string;\n readonly input: NonNullable<unknown>;\n readonly scope: string;\n readonly context?:\n | {\n readonly signer?:\n | {\n readonly signatures: ReadonlyArray<string>;\n readonly user?:\n | {\n readonly address: string;\n readonly networkId: string;\n readonly chainId: number;\n }\n | null\n | undefined;\n readonly app?:\n | { readonly name: string; readonly key: string }\n | null\n | undefined;\n }\n | null\n | undefined;\n }\n | null\n | undefined;\n };\n }>;\n };\n};\n\nexport type GetJobStatusQueryVariables = Exact<{\n jobId: Scalars[\"String\"][\"input\"];\n}>;\n\nexport type GetJobStatusQuery = {\n readonly jobStatus?:\n | {\n readonly id: string;\n readonly status: string;\n readonly result?: NonNullable<unknown> | null | undefined;\n readonly error?: string | null | undefined;\n readonly createdAt: string | Date;\n readonly completedAt?: string | Date | null | undefined;\n }\n | null\n | undefined;\n};\n\nexport type EvaluateActionsQueryVariables = Exact<{\n documentIdentifier: Scalars[\"String\"][\"input\"];\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n candidates: ReadonlyArray<ActionCandidateInput>;\n}>;\n\nexport type EvaluateActionsQuery = {\n readonly evaluateActions: {\n readonly allAllowed: boolean;\n readonly anyAllowed: boolean;\n readonly allDenied: boolean;\n readonly anyDenied: boolean;\n readonly evaluations: ReadonlyArray<{\n readonly decision: AuthDecision;\n readonly reason?: string | null | undefined;\n }>;\n };\n};\n\nexport type CreateDocumentMutationVariables = Exact<{\n document: Scalars[\"JSONObject\"][\"input\"];\n parentIdentifier?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type CreateDocumentMutation = {\n readonly createDocument: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type CreateEmptyDocumentMutationVariables = Exact<{\n documentType: Scalars[\"String\"][\"input\"];\n parentIdentifier?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type CreateEmptyDocumentMutation = {\n readonly createEmptyDocument: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type MutateDocumentMutationVariables = Exact<{\n documentIdentifier: Scalars[\"String\"][\"input\"];\n actions: ReadonlyArray<ActionInput>;\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type MutateDocumentMutation = {\n readonly mutateDocument: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type MutateDocumentAsyncMutationVariables = Exact<{\n documentIdentifier: Scalars[\"String\"][\"input\"];\n actions: ReadonlyArray<ActionInput>;\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type MutateDocumentAsyncMutation = {\n readonly mutateDocumentAsync: {\n readonly id: string;\n readonly status: string;\n readonly result?: NonNullable<unknown> | null | undefined;\n readonly error?: string | null | undefined;\n readonly createdAt: string | Date;\n readonly completedAt?: string | Date | null | undefined;\n };\n};\n\nexport type RenameDocumentMutationVariables = Exact<{\n documentIdentifier: Scalars[\"String\"][\"input\"];\n name: Scalars[\"String\"][\"input\"];\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type RenameDocumentMutation = {\n readonly renameDocument: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type SetPreferredEditorMutationVariables = Exact<{\n documentIdentifier: Scalars[\"String\"][\"input\"];\n preferredEditor?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type SetPreferredEditorMutation = {\n readonly setPreferredEditor: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type AddRelationshipMutationVariables = Exact<{\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType: Scalars[\"String\"][\"input\"];\n metadata?: InputMaybe<Scalars[\"JSONObject\"][\"input\"]>;\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type AddRelationshipMutation = {\n readonly addRelationship: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type UpdateRelationshipMutationVariables = Exact<{\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType: Scalars[\"String\"][\"input\"];\n metadata?: InputMaybe<Scalars[\"JSONObject\"][\"input\"]>;\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type UpdateRelationshipMutation = {\n readonly updateRelationship: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type RemoveRelationshipMutationVariables = Exact<{\n sourceIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType: Scalars[\"String\"][\"input\"];\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type RemoveRelationshipMutation = {\n readonly removeRelationship: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n};\n\nexport type MoveRelationshipMutationVariables = Exact<{\n sourceParentIdentifier: Scalars[\"String\"][\"input\"];\n targetParentIdentifier: Scalars[\"String\"][\"input\"];\n targetIdentifier: Scalars[\"String\"][\"input\"];\n relationshipType: Scalars[\"String\"][\"input\"];\n branch?: InputMaybe<Scalars[\"String\"][\"input\"]>;\n}>;\n\nexport type MoveRelationshipMutation = {\n readonly moveRelationship: {\n readonly source: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n readonly target: {\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n };\n };\n};\n\nexport type DeleteDocumentMutationVariables = Exact<{\n identifier: Scalars[\"String\"][\"input\"];\n propagate?: InputMaybe<PropagationMode>;\n}>;\n\nexport type DeleteDocumentMutation = { readonly deleteDocument: boolean };\n\nexport type DeleteDocumentsMutationVariables = Exact<{\n identifiers: ReadonlyArray<Scalars[\"String\"][\"input\"]>;\n propagate?: InputMaybe<PropagationMode>;\n}>;\n\nexport type DeleteDocumentsMutation = { readonly deleteDocuments: boolean };\n\nexport type DocumentChangesSubscriptionVariables = Exact<{\n search?: InputMaybe<SearchFilterInput>;\n view?: InputMaybe<ViewFilterInput>;\n}>;\n\nexport type DocumentChangesSubscription = {\n readonly documentChanges: {\n readonly type: DocumentChangeType;\n readonly documents: ReadonlyArray<{\n readonly id: string;\n readonly slug?: string | null | undefined;\n readonly name: string;\n readonly documentType: string;\n readonly state: NonNullable<unknown>;\n readonly createdAtUtcIso: string | Date;\n readonly lastModifiedAtUtcIso: string | Date;\n readonly revisionsList: ReadonlyArray<{\n readonly scope: string;\n readonly revision: number;\n }>;\n }>;\n readonly context?:\n | {\n readonly parentId?: string | null | undefined;\n readonly childId?: string | null | undefined;\n }\n | null\n | undefined;\n };\n};\n\nexport type JobChangesSubscriptionVariables = Exact<{\n jobId: Scalars[\"String\"][\"input\"];\n}>;\n\nexport type JobChangesSubscription = {\n readonly jobChanges: {\n readonly jobId: string;\n readonly status: string;\n readonly result?: NonNullable<unknown> | null | undefined;\n readonly error?: string | null | undefined;\n };\n};\n\nexport type PollSyncEnvelopesQueryVariables = Exact<{\n channelId: Scalars[\"String\"][\"input\"];\n outboxAck: Scalars[\"Int\"][\"input\"];\n outboxLatest: Scalars[\"Int\"][\"input\"];\n}>;\n\nexport type PollSyncEnvelopesQuery = {\n readonly pollSyncEnvelopes: {\n readonly ackOrdinal: number;\n readonly hasMore: boolean;\n readonly envelopes: ReadonlyArray<{\n readonly type: SyncEnvelopeType;\n readonly key?: string | null | undefined;\n readonly dependsOn?: ReadonlyArray<string> | null | undefined;\n readonly channelMeta: { readonly id: string };\n readonly operations?:\n | ReadonlyArray<{\n readonly operation: {\n readonly index: number;\n readonly timestampUtcMs: string;\n readonly hash: string;\n readonly skip: number;\n readonly error?: string | null | undefined;\n readonly deniedReason?: string | null | undefined;\n readonly id?: string | null | undefined;\n readonly action: {\n readonly id: string;\n readonly type: string;\n readonly timestampUtcMs: string;\n readonly input: NonNullable<unknown>;\n readonly scope: string;\n readonly context?:\n | {\n readonly signer?:\n | {\n readonly signatures: ReadonlyArray<string>;\n readonly user?:\n | {\n readonly address: string;\n readonly networkId: string;\n readonly chainId: number;\n }\n | null\n | undefined;\n readonly app?:\n | { readonly name: string; readonly key: string }\n | null\n | undefined;\n }\n | null\n | undefined;\n }\n | null\n | undefined;\n };\n };\n readonly context: {\n readonly documentId: string;\n readonly documentType: string;\n readonly scope: string;\n readonly branch: string;\n };\n }>\n | null\n | undefined;\n readonly cursor?:\n | {\n readonly remoteName: string;\n readonly cursorOrdinal: number;\n readonly lastSyncedAtUtcMs?: string | null | undefined;\n }\n | null\n | undefined;\n }>;\n readonly deadLetters: ReadonlyArray<{\n readonly documentId: string;\n readonly error: string;\n readonly errorType?: string | null | undefined;\n }>;\n };\n};\n\nexport type TouchChannelMutationVariables = Exact<{\n input: TouchChannelInput;\n}>;\n\nexport type TouchChannelMutation = {\n readonly touchChannel: {\n readonly success: boolean;\n readonly ackOrdinal: number;\n };\n};\n\nexport type PushSyncEnvelopesMutationVariables = Exact<{\n envelopes: ReadonlyArray<SyncEnvelopeInput>;\n}>;\n\nexport type PushSyncEnvelopesMutation = { readonly pushSyncEnvelopes: boolean };\n\nexport type WithIndex<TObject> = TObject & Record<string, any>;\nexport type ResolversObject<TObject> = WithIndex<TObject>;\n\nexport type ResolverTypeWrapper<T> = Promise<T> | T;\n\nexport type ResolverWithResolve<TResult, TParent, TContext, TArgs> = {\n resolve: ResolverFn<TResult, TParent, TContext, TArgs>;\n};\nexport type Resolver<\n TResult,\n TParent = Record<PropertyKey, never>,\n TContext = Record<PropertyKey, never>,\n TArgs = Record<PropertyKey, never>,\n> =\n | ResolverFn<TResult, TParent, TContext, TArgs>\n | ResolverWithResolve<TResult, TParent, TContext, TArgs>;\n\nexport type ResolverFn<TResult, TParent, TContext, TArgs> = (\n parent: TParent,\n args: TArgs,\n context: TContext,\n info: GraphQLResolveInfo,\n) => Promise<TResult> | TResult;\n\nexport type SubscriptionSubscribeFn<TResult, TParent, TContext, TArgs> = (\n parent: TParent,\n args: TArgs,\n context: TContext,\n info: GraphQLResolveInfo,\n) => AsyncIterable<TResult> | Promise<AsyncIterable<TResult>>;\n\nexport type SubscriptionResolveFn<TResult, TParent, TContext, TArgs> = (\n parent: TParent,\n args: TArgs,\n context: TContext,\n info: GraphQLResolveInfo,\n) => TResult | Promise<TResult>;\n\nexport interface SubscriptionSubscriberObject<\n TResult,\n TKey extends string,\n TParent,\n TContext,\n TArgs,\n> {\n subscribe: SubscriptionSubscribeFn<\n { [key in TKey]: TResult },\n TParent,\n TContext,\n TArgs\n >;\n resolve?: SubscriptionResolveFn<\n TResult,\n { [key in TKey]: TResult },\n TContext,\n TArgs\n >;\n}\n\nexport interface SubscriptionResolverObject<TResult, TParent, TContext, TArgs> {\n subscribe: SubscriptionSubscribeFn<any, TParent, TContext, TArgs>;\n resolve: SubscriptionResolveFn<TResult, any, TContext, TArgs>;\n}\n\nexport type SubscriptionObject<\n TResult,\n TKey extends string,\n TParent,\n TContext,\n TArgs,\n> =\n | SubscriptionSubscriberObject<TResult, TKey, TParent, TContext, TArgs>\n | SubscriptionResolverObject<TResult, TParent, TContext, TArgs>;\n\nexport type SubscriptionResolver<\n TResult,\n TKey extends string,\n TParent = Record<PropertyKey, never>,\n TContext = Record<PropertyKey, never>,\n TArgs = Record<PropertyKey, never>,\n> =\n | ((\n ...args: any[]\n ) => SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>)\n | SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>;\n\nexport type TypeResolveFn<\n TTypes,\n TParent = Record<PropertyKey, never>,\n TContext = Record<PropertyKey, never>,\n> = (\n parent: TParent,\n context: TContext,\n info: GraphQLResolveInfo,\n) => Maybe<TTypes> | Promise<Maybe<TTypes>>;\n\nexport type IsTypeOfResolverFn<\n T = Record<PropertyKey, never>,\n TContext = Record<PropertyKey, never>,\n> = (\n obj: T,\n context: TContext,\n info: GraphQLResolveInfo,\n) => boolean | Promise<boolean>;\n\nexport type NextResolverFn<T> = () => Promise<T>;\n\nexport type DirectiveResolverFn<\n TResult = Record<PropertyKey, never>,\n TParent = Record<PropertyKey, never>,\n TContext = Record<PropertyKey, never>,\n TArgs = Record<PropertyKey, never>,\n> = (\n next: NextResolverFn<TResult>,\n parent: TParent,\n args: TArgs,\n context: TContext,\n info: GraphQLResolveInfo,\n) => TResult | Promise<TResult>;\n\n/** Mapping between all available schema types and the resolvers types */\nexport type ResolversTypes = ResolversObject<{\n Action: ResolverTypeWrapper<Action>;\n ActionCandidateInput: ActionCandidateInput;\n ActionContext: ResolverTypeWrapper<ActionContext>;\n ActionContextInput: ActionContextInput;\n ActionEvaluation: ResolverTypeWrapper<ActionEvaluation>;\n ActionEvaluations: ResolverTypeWrapper<ActionEvaluations>;\n ActionInput: ActionInput;\n AuthDecision: AuthDecision;\n Boolean: ResolverTypeWrapper<Scalars[\"Boolean\"][\"output\"]>;\n ChannelMeta: ResolverTypeWrapper<ChannelMeta>;\n ChannelMetaInput: ChannelMetaInput;\n DateTime: ResolverTypeWrapper<Scalars[\"DateTime\"][\"output\"]>;\n DeadLetterInfo: ResolverTypeWrapper<DeadLetterInfo>;\n DocumentChangeContext: ResolverTypeWrapper<DocumentChangeContext>;\n DocumentChangeEvent: ResolverTypeWrapper<DocumentChangeEvent>;\n DocumentChangeType: DocumentChangeType;\n DocumentModelGlobalState: ResolverTypeWrapper<DocumentModelGlobalState>;\n DocumentModelResultPage: ResolverTypeWrapper<DocumentModelResultPage>;\n DocumentOperationsFilterInput: DocumentOperationsFilterInput;\n DocumentRelationship: ResolverTypeWrapper<DocumentRelationship>;\n DocumentRelationshipResultPage: ResolverTypeWrapper<DocumentRelationshipResultPage>;\n DocumentWithChildren: ResolverTypeWrapper<DocumentWithChildren>;\n Int: ResolverTypeWrapper<Scalars[\"Int\"][\"output\"]>;\n JSONObject: ResolverTypeWrapper<Scalars[\"JSONObject\"][\"output\"]>;\n JobChangeEvent: ResolverTypeWrapper<JobChangeEvent>;\n JobInfo: ResolverTypeWrapper<JobInfo>;\n MoveRelationshipResult: ResolverTypeWrapper<MoveRelationshipResult>;\n Mutation: ResolverTypeWrapper<Record<PropertyKey, never>>;\n OperationContext: ResolverTypeWrapper<OperationContext>;\n OperationContextInput: OperationContextInput;\n OperationInput: OperationInput;\n OperationWithContext: ResolverTypeWrapper<OperationWithContext>;\n OperationWithContextInput: OperationWithContextInput;\n OperationsFilterInput: OperationsFilterInput;\n PHDocument: ResolverTypeWrapper<PhDocument>;\n PHDocumentResultPage: ResolverTypeWrapper<PhDocumentResultPage>;\n PagingInput: PagingInput;\n PollSyncEnvelopesResult: ResolverTypeWrapper<PollSyncEnvelopesResult>;\n PropagationMode: PropagationMode;\n Query: ResolverTypeWrapper<Record<PropertyKey, never>>;\n ReactorOperation: ResolverTypeWrapper<ReactorOperation>;\n ReactorOperationResultPage: ResolverTypeWrapper<ReactorOperationResultPage>;\n ReactorSigner: ResolverTypeWrapper<ReactorSigner>;\n ReactorSignerApp: ResolverTypeWrapper<ReactorSignerApp>;\n ReactorSignerAppInput: ReactorSignerAppInput;\n ReactorSignerInput: ReactorSignerInput;\n ReactorSignerUser: ResolverTypeWrapper<ReactorSignerUser>;\n ReactorSignerUserInput: ReactorSignerUserInput;\n RemoteCursor: ResolverTypeWrapper<RemoteCursor>;\n RemoteCursorInput: RemoteCursorInput;\n RemoteFilterInput: RemoteFilterInput;\n Revision: ResolverTypeWrapper<Revision>;\n SearchFilterInput: SearchFilterInput;\n String: ResolverTypeWrapper<Scalars[\"String\"][\"output\"]>;\n Subscription: ResolverTypeWrapper<Record<PropertyKey, never>>;\n SyncEnvelope: ResolverTypeWrapper<SyncEnvelope>;\n SyncEnvelopeInput: SyncEnvelopeInput;\n SyncEnvelopeType: SyncEnvelopeType;\n TouchChannelInput: TouchChannelInput;\n TouchChannelResult: ResolverTypeWrapper<TouchChannelResult>;\n ViewFilterInput: ViewFilterInput;\n}>;\n\n/** Mapping between all available schema types and the resolvers parents */\nexport type ResolversParentTypes = ResolversObject<{\n Action: Action;\n ActionCandidateInput: ActionCandidateInput;\n ActionContext: ActionContext;\n ActionContextInput: ActionContextInput;\n ActionEvaluation: ActionEvaluation;\n ActionEvaluations: ActionEvaluations;\n ActionInput: ActionInput;\n Boolean: Scalars[\"Boolean\"][\"output\"];\n ChannelMeta: ChannelMeta;\n ChannelMetaInput: ChannelMetaInput;\n DateTime: Scalars[\"DateTime\"][\"output\"];\n DeadLetterInfo: DeadLetterInfo;\n DocumentChangeContext: DocumentChangeContext;\n DocumentChangeEvent: DocumentChangeEvent;\n DocumentModelGlobalState: DocumentModelGlobalState;\n DocumentModelResultPage: DocumentModelResultPage;\n DocumentOperationsFilterInput: DocumentOperationsFilterInput;\n DocumentRelationship: DocumentRelationship;\n DocumentRelationshipResultPage: DocumentRelationshipResultPage;\n DocumentWithChildren: DocumentWithChildren;\n Int: Scalars[\"Int\"][\"output\"];\n JSONObject: Scalars[\"JSONObject\"][\"output\"];\n JobChangeEvent: JobChangeEvent;\n JobInfo: JobInfo;\n MoveRelationshipResult: MoveRelationshipResult;\n Mutation: Record<PropertyKey, never>;\n OperationContext: OperationContext;\n OperationContextInput: OperationContextInput;\n OperationInput: OperationInput;\n OperationWithContext: OperationWithContext;\n OperationWithContextInput: OperationWithContextInput;\n OperationsFilterInput: OperationsFilterInput;\n PHDocument: PhDocument;\n PHDocumentResultPage: PhDocumentResultPage;\n PagingInput: PagingInput;\n PollSyncEnvelopesResult: PollSyncEnvelopesResult;\n Query: Record<PropertyKey, never>;\n ReactorOperation: ReactorOperation;\n ReactorOperationResultPage: ReactorOperationResultPage;\n ReactorSigner: ReactorSigner;\n ReactorSignerApp: ReactorSignerApp;\n ReactorSignerAppInput: ReactorSignerAppInput;\n ReactorSignerInput: ReactorSignerInput;\n ReactorSignerUser: ReactorSignerUser;\n ReactorSignerUserInput: ReactorSignerUserInput;\n RemoteCursor: RemoteCursor;\n RemoteCursorInput: RemoteCursorInput;\n RemoteFilterInput: RemoteFilterInput;\n Revision: Revision;\n SearchFilterInput: SearchFilterInput;\n String: Scalars[\"String\"][\"output\"];\n Subscription: Record<PropertyKey, never>;\n SyncEnvelope: SyncEnvelope;\n SyncEnvelopeInput: SyncEnvelopeInput;\n TouchChannelInput: TouchChannelInput;\n TouchChannelResult: TouchChannelResult;\n ViewFilterInput: ViewFilterInput;\n}>;\n\nexport type ActionResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"Action\"] =\n ResolversParentTypes[\"Action\"],\n> = ResolversObject<{\n context?: Resolver<\n Maybe<ResolversTypes[\"ActionContext\"]>,\n ParentType,\n ContextType\n >;\n id?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n input?: Resolver<ResolversTypes[\"JSONObject\"], ParentType, ContextType>;\n scope?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n timestampUtcMs?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n type?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type ActionContextResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ActionContext\"] =\n ResolversParentTypes[\"ActionContext\"],\n> = ResolversObject<{\n signer?: Resolver<\n Maybe<ResolversTypes[\"ReactorSigner\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type ActionEvaluationResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ActionEvaluation\"] =\n ResolversParentTypes[\"ActionEvaluation\"],\n> = ResolversObject<{\n decision?: Resolver<ResolversTypes[\"AuthDecision\"], ParentType, ContextType>;\n reason?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n}>;\n\nexport type ActionEvaluationsResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ActionEvaluations\"] =\n ResolversParentTypes[\"ActionEvaluations\"],\n> = ResolversObject<{\n allAllowed?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n allDenied?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n anyAllowed?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n anyDenied?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n evaluations?: Resolver<\n ReadonlyArray<ResolversTypes[\"ActionEvaluation\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type ChannelMetaResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ChannelMeta\"] =\n ResolversParentTypes[\"ChannelMeta\"],\n> = ResolversObject<{\n id?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport interface DateTimeScalarConfig extends GraphQLScalarTypeConfig<\n ResolversTypes[\"DateTime\"],\n any\n> {\n name: \"DateTime\";\n}\n\nexport type DeadLetterInfoResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DeadLetterInfo\"] =\n ResolversParentTypes[\"DeadLetterInfo\"],\n> = ResolversObject<{\n branch?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n documentId?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n error?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n errorType?: Resolver<\n Maybe<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n jobId?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n operationCount?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n scopes?: Resolver<\n ReadonlyArray<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type DocumentChangeContextResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DocumentChangeContext\"] =\n ResolversParentTypes[\"DocumentChangeContext\"],\n> = ResolversObject<{\n childId?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n parentId?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n}>;\n\nexport type DocumentChangeEventResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DocumentChangeEvent\"] =\n ResolversParentTypes[\"DocumentChangeEvent\"],\n> = ResolversObject<{\n context?: Resolver<\n Maybe<ResolversTypes[\"DocumentChangeContext\"]>,\n ParentType,\n ContextType\n >;\n documents?: Resolver<\n ReadonlyArray<ResolversTypes[\"PHDocument\"]>,\n ParentType,\n ContextType\n >;\n type?: Resolver<\n ResolversTypes[\"DocumentChangeType\"],\n ParentType,\n ContextType\n >;\n}>;\n\nexport type DocumentModelGlobalStateResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DocumentModelGlobalState\"] =\n ResolversParentTypes[\"DocumentModelGlobalState\"],\n> = ResolversObject<{\n id?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n name?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n namespace?: Resolver<\n Maybe<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n specification?: Resolver<\n ResolversTypes[\"JSONObject\"],\n ParentType,\n ContextType\n >;\n version?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n}>;\n\nexport type DocumentModelResultPageResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DocumentModelResultPage\"] =\n ResolversParentTypes[\"DocumentModelResultPage\"],\n> = ResolversObject<{\n cursor?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n hasNextPage?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n hasPreviousPage?: Resolver<\n ResolversTypes[\"Boolean\"],\n ParentType,\n ContextType\n >;\n items?: Resolver<\n ReadonlyArray<ResolversTypes[\"DocumentModelGlobalState\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type DocumentRelationshipResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DocumentRelationship\"] =\n ResolversParentTypes[\"DocumentRelationship\"],\n> = ResolversObject<{\n createdAt?: Resolver<ResolversTypes[\"DateTime\"], ParentType, ContextType>;\n metadata?: Resolver<\n Maybe<ResolversTypes[\"JSONObject\"]>,\n ParentType,\n ContextType\n >;\n relationshipType?: Resolver<\n ResolversTypes[\"String\"],\n ParentType,\n ContextType\n >;\n sourceId?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n targetId?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n updatedAt?: Resolver<ResolversTypes[\"DateTime\"], ParentType, ContextType>;\n}>;\n\nexport type DocumentRelationshipResultPageResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DocumentRelationshipResultPage\"] =\n ResolversParentTypes[\"DocumentRelationshipResultPage\"],\n> = ResolversObject<{\n cursor?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n hasNextPage?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n hasPreviousPage?: Resolver<\n ResolversTypes[\"Boolean\"],\n ParentType,\n ContextType\n >;\n items?: Resolver<\n ReadonlyArray<ResolversTypes[\"DocumentRelationship\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type DocumentWithChildrenResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"DocumentWithChildren\"] =\n ResolversParentTypes[\"DocumentWithChildren\"],\n> = ResolversObject<{\n childIds?: Resolver<\n ReadonlyArray<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n document?: Resolver<ResolversTypes[\"PHDocument\"], ParentType, ContextType>;\n}>;\n\nexport interface JsonObjectScalarConfig extends GraphQLScalarTypeConfig<\n ResolversTypes[\"JSONObject\"],\n any\n> {\n name: \"JSONObject\";\n}\n\nexport type JobChangeEventResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"JobChangeEvent\"] =\n ResolversParentTypes[\"JobChangeEvent\"],\n> = ResolversObject<{\n error?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n jobId?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n result?: Resolver<\n Maybe<ResolversTypes[\"JSONObject\"]>,\n ParentType,\n ContextType\n >;\n status?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type JobInfoResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"JobInfo\"] =\n ResolversParentTypes[\"JobInfo\"],\n> = ResolversObject<{\n completedAt?: Resolver<\n Maybe<ResolversTypes[\"DateTime\"]>,\n ParentType,\n ContextType\n >;\n createdAt?: Resolver<ResolversTypes[\"DateTime\"], ParentType, ContextType>;\n error?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n id?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n result?: Resolver<\n Maybe<ResolversTypes[\"JSONObject\"]>,\n ParentType,\n ContextType\n >;\n status?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type MoveRelationshipResultResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"MoveRelationshipResult\"] =\n ResolversParentTypes[\"MoveRelationshipResult\"],\n> = ResolversObject<{\n source?: Resolver<ResolversTypes[\"PHDocument\"], ParentType, ContextType>;\n target?: Resolver<ResolversTypes[\"PHDocument\"], ParentType, ContextType>;\n}>;\n\nexport type MutationResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"Mutation\"] =\n ResolversParentTypes[\"Mutation\"],\n> = ResolversObject<{\n addRelationship?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<\n MutationAddRelationshipArgs,\n \"relationshipType\" | \"sourceIdentifier\" | \"targetIdentifier\"\n >\n >;\n createDocument?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<MutationCreateDocumentArgs, \"document\">\n >;\n createEmptyDocument?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<MutationCreateEmptyDocumentArgs, \"documentType\">\n >;\n deleteDocument?: Resolver<\n ResolversTypes[\"Boolean\"],\n ParentType,\n ContextType,\n RequireFields<MutationDeleteDocumentArgs, \"identifier\">\n >;\n deleteDocuments?: Resolver<\n ResolversTypes[\"Boolean\"],\n ParentType,\n ContextType,\n RequireFields<MutationDeleteDocumentsArgs, \"identifiers\">\n >;\n execute?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<MutationExecuteArgs, \"actions\" | \"documentIdentifier\">\n >;\n executeAsync?: Resolver<\n ResolversTypes[\"JobInfo\"],\n ParentType,\n ContextType,\n RequireFields<MutationExecuteAsyncArgs, \"actions\" | \"documentIdentifier\">\n >;\n moveRelationship?: Resolver<\n ResolversTypes[\"MoveRelationshipResult\"],\n ParentType,\n ContextType,\n RequireFields<\n MutationMoveRelationshipArgs,\n | \"relationshipType\"\n | \"sourceParentIdentifier\"\n | \"targetIdentifier\"\n | \"targetParentIdentifier\"\n >\n >;\n mutateDocument?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<MutationMutateDocumentArgs, \"actions\" | \"documentIdentifier\">\n >;\n mutateDocumentAsync?: Resolver<\n ResolversTypes[\"String\"],\n ParentType,\n ContextType,\n RequireFields<\n MutationMutateDocumentAsyncArgs,\n \"actions\" | \"documentIdentifier\"\n >\n >;\n pushSyncEnvelopes?: Resolver<\n ResolversTypes[\"Boolean\"],\n ParentType,\n ContextType,\n RequireFields<MutationPushSyncEnvelopesArgs, \"envelopes\">\n >;\n removeRelationship?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<\n MutationRemoveRelationshipArgs,\n \"relationshipType\" | \"sourceIdentifier\" | \"targetIdentifier\"\n >\n >;\n renameDocument?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<MutationRenameDocumentArgs, \"documentIdentifier\" | \"name\">\n >;\n setPreferredEditor?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<MutationSetPreferredEditorArgs, \"documentIdentifier\">\n >;\n touchChannel?: Resolver<\n ResolversTypes[\"TouchChannelResult\"],\n ParentType,\n ContextType,\n RequireFields<MutationTouchChannelArgs, \"input\">\n >;\n updateRelationship?: Resolver<\n ResolversTypes[\"PHDocument\"],\n ParentType,\n ContextType,\n RequireFields<\n MutationUpdateRelationshipArgs,\n \"relationshipType\" | \"sourceIdentifier\" | \"targetIdentifier\"\n >\n >;\n}>;\n\nexport type OperationContextResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"OperationContext\"] =\n ResolversParentTypes[\"OperationContext\"],\n> = ResolversObject<{\n branch?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n documentId?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n documentType?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n ordinal?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n scope?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type OperationWithContextResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"OperationWithContext\"] =\n ResolversParentTypes[\"OperationWithContext\"],\n> = ResolversObject<{\n context?: Resolver<\n ResolversTypes[\"OperationContext\"],\n ParentType,\n ContextType\n >;\n operation?: Resolver<\n ResolversTypes[\"ReactorOperation\"],\n ParentType,\n ContextType\n >;\n}>;\n\nexport type PhDocumentResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"PHDocument\"] =\n ResolversParentTypes[\"PHDocument\"],\n> = ResolversObject<{\n createdAtUtcIso?: Resolver<\n ResolversTypes[\"DateTime\"],\n ParentType,\n ContextType\n >;\n documentType?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n id?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n lastModifiedAtUtcIso?: Resolver<\n ResolversTypes[\"DateTime\"],\n ParentType,\n ContextType\n >;\n name?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n operations?: Resolver<\n Maybe<ResolversTypes[\"ReactorOperationResultPage\"]>,\n ParentType,\n ContextType,\n Partial<PhDocumentOperationsArgs>\n >;\n preferredEditor?: Resolver<\n Maybe<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n revisionsList?: Resolver<\n ReadonlyArray<ResolversTypes[\"Revision\"]>,\n ParentType,\n ContextType\n >;\n slug?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n state?: Resolver<ResolversTypes[\"JSONObject\"], ParentType, ContextType>;\n}>;\n\nexport type PhDocumentResultPageResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"PHDocumentResultPage\"] =\n ResolversParentTypes[\"PHDocumentResultPage\"],\n> = ResolversObject<{\n cursor?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n hasNextPage?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n hasPreviousPage?: Resolver<\n ResolversTypes[\"Boolean\"],\n ParentType,\n ContextType\n >;\n items?: Resolver<\n ReadonlyArray<ResolversTypes[\"PHDocument\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type PollSyncEnvelopesResultResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"PollSyncEnvelopesResult\"] =\n ResolversParentTypes[\"PollSyncEnvelopesResult\"],\n> = ResolversObject<{\n ackOrdinal?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n deadLetters?: Resolver<\n ReadonlyArray<ResolversTypes[\"DeadLetterInfo\"]>,\n ParentType,\n ContextType\n >;\n envelopes?: Resolver<\n ReadonlyArray<ResolversTypes[\"SyncEnvelope\"]>,\n ParentType,\n ContextType\n >;\n hasMore?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n}>;\n\nexport type QueryResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"Query\"] =\n ResolversParentTypes[\"Query\"],\n> = ResolversObject<{\n document?: Resolver<\n Maybe<ResolversTypes[\"DocumentWithChildren\"]>,\n ParentType,\n ContextType,\n RequireFields<QueryDocumentArgs, \"identifier\">\n >;\n documentIncomingRelationshipEdges?: Resolver<\n ResolversTypes[\"DocumentRelationshipResultPage\"],\n ParentType,\n ContextType,\n RequireFields<\n QueryDocumentIncomingRelationshipEdgesArgs,\n \"targetIdentifier\"\n >\n >;\n documentIncomingRelationships?: Resolver<\n ResolversTypes[\"PHDocumentResultPage\"],\n ParentType,\n ContextType,\n RequireFields<\n QueryDocumentIncomingRelationshipsArgs,\n \"relationshipType\" | \"targetIdentifier\"\n >\n >;\n documentModels?: Resolver<\n ResolversTypes[\"DocumentModelResultPage\"],\n ParentType,\n ContextType,\n Partial<QueryDocumentModelsArgs>\n >;\n documentOperations?: Resolver<\n ResolversTypes[\"ReactorOperationResultPage\"],\n ParentType,\n ContextType,\n RequireFields<QueryDocumentOperationsArgs, \"filter\">\n >;\n documentOutgoingRelationshipEdges?: Resolver<\n ResolversTypes[\"DocumentRelationshipResultPage\"],\n ParentType,\n ContextType,\n RequireFields<\n QueryDocumentOutgoingRelationshipEdgesArgs,\n \"sourceIdentifier\"\n >\n >;\n documentOutgoingRelationships?: Resolver<\n ResolversTypes[\"PHDocumentResultPage\"],\n ParentType,\n ContextType,\n RequireFields<\n QueryDocumentOutgoingRelationshipsArgs,\n \"relationshipType\" | \"sourceIdentifier\"\n >\n >;\n evaluateActions?: Resolver<\n ResolversTypes[\"ActionEvaluations\"],\n ParentType,\n ContextType,\n RequireFields<QueryEvaluateActionsArgs, \"candidates\" | \"documentIdentifier\">\n >;\n findDocuments?: Resolver<\n ResolversTypes[\"PHDocumentResultPage\"],\n ParentType,\n ContextType,\n Partial<QueryFindDocumentsArgs>\n >;\n jobStatus?: Resolver<\n Maybe<ResolversTypes[\"JobInfo\"]>,\n ParentType,\n ContextType,\n RequireFields<QueryJobStatusArgs, \"jobId\">\n >;\n pollSyncEnvelopes?: Resolver<\n ResolversTypes[\"PollSyncEnvelopesResult\"],\n ParentType,\n ContextType,\n RequireFields<\n QueryPollSyncEnvelopesArgs,\n \"channelId\" | \"outboxAck\" | \"outboxLatest\"\n >\n >;\n}>;\n\nexport type ReactorOperationResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ReactorOperation\"] =\n ResolversParentTypes[\"ReactorOperation\"],\n> = ResolversObject<{\n action?: Resolver<ResolversTypes[\"Action\"], ParentType, ContextType>;\n deniedReason?: Resolver<\n Maybe<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n error?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n hash?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n id?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n index?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n skip?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n timestampUtcMs?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type ReactorOperationResultPageResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ReactorOperationResultPage\"] =\n ResolversParentTypes[\"ReactorOperationResultPage\"],\n> = ResolversObject<{\n cursor?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n hasNextPage?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n hasPreviousPage?: Resolver<\n ResolversTypes[\"Boolean\"],\n ParentType,\n ContextType\n >;\n items?: Resolver<\n ReadonlyArray<ResolversTypes[\"ReactorOperation\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type ReactorSignerResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ReactorSigner\"] =\n ResolversParentTypes[\"ReactorSigner\"],\n> = ResolversObject<{\n app?: Resolver<\n Maybe<ResolversTypes[\"ReactorSignerApp\"]>,\n ParentType,\n ContextType\n >;\n signatures?: Resolver<\n ReadonlyArray<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n user?: Resolver<\n Maybe<ResolversTypes[\"ReactorSignerUser\"]>,\n ParentType,\n ContextType\n >;\n}>;\n\nexport type ReactorSignerAppResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ReactorSignerApp\"] =\n ResolversParentTypes[\"ReactorSignerApp\"],\n> = ResolversObject<{\n key?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n name?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type ReactorSignerUserResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"ReactorSignerUser\"] =\n ResolversParentTypes[\"ReactorSignerUser\"],\n> = ResolversObject<{\n address?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n chainId?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n networkId?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type RemoteCursorResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"RemoteCursor\"] =\n ResolversParentTypes[\"RemoteCursor\"],\n> = ResolversObject<{\n cursorOrdinal?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n lastSyncedAtUtcMs?: Resolver<\n Maybe<ResolversTypes[\"String\"]>,\n ParentType,\n ContextType\n >;\n remoteName?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type RevisionResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"Revision\"] =\n ResolversParentTypes[\"Revision\"],\n> = ResolversObject<{\n revision?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n scope?: Resolver<ResolversTypes[\"String\"], ParentType, ContextType>;\n}>;\n\nexport type SubscriptionResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"Subscription\"] =\n ResolversParentTypes[\"Subscription\"],\n> = ResolversObject<{\n documentChanges?: SubscriptionResolver<\n ResolversTypes[\"DocumentChangeEvent\"],\n \"documentChanges\",\n ParentType,\n ContextType,\n Partial<SubscriptionDocumentChangesArgs>\n >;\n jobChanges?: SubscriptionResolver<\n ResolversTypes[\"JobChangeEvent\"],\n \"jobChanges\",\n ParentType,\n ContextType,\n RequireFields<SubscriptionJobChangesArgs, \"jobId\">\n >;\n}>;\n\nexport type SyncEnvelopeResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"SyncEnvelope\"] =\n ResolversParentTypes[\"SyncEnvelope\"],\n> = ResolversObject<{\n channelMeta?: Resolver<\n ResolversTypes[\"ChannelMeta\"],\n ParentType,\n ContextType\n >;\n cursor?: Resolver<\n Maybe<ResolversTypes[\"RemoteCursor\"]>,\n ParentType,\n ContextType\n >;\n dependsOn?: Resolver<\n Maybe<ReadonlyArray<ResolversTypes[\"String\"]>>,\n ParentType,\n ContextType\n >;\n key?: Resolver<Maybe<ResolversTypes[\"String\"]>, ParentType, ContextType>;\n operations?: Resolver<\n Maybe<ReadonlyArray<ResolversTypes[\"OperationWithContext\"]>>,\n ParentType,\n ContextType\n >;\n type?: Resolver<ResolversTypes[\"SyncEnvelopeType\"], ParentType, ContextType>;\n}>;\n\nexport type TouchChannelResultResolvers<\n ContextType = Context,\n ParentType extends ResolversParentTypes[\"TouchChannelResult\"] =\n ResolversParentTypes[\"TouchChannelResult\"],\n> = ResolversObject<{\n ackOrdinal?: Resolver<ResolversTypes[\"Int\"], ParentType, ContextType>;\n success?: Resolver<ResolversTypes[\"Boolean\"], ParentType, ContextType>;\n}>;\n\nexport type Resolvers<ContextType = Context> = ResolversObject<{\n Action?: ActionResolvers<ContextType>;\n ActionContext?: ActionContextResolvers<ContextType>;\n ActionEvaluation?: ActionEvaluationResolvers<ContextType>;\n ActionEvaluations?: ActionEvaluationsResolvers<ContextType>;\n ChannelMeta?: ChannelMetaResolvers<ContextType>;\n DateTime?: GraphQLScalarType;\n DeadLetterInfo?: DeadLetterInfoResolvers<ContextType>;\n DocumentChangeContext?: DocumentChangeContextResolvers<ContextType>;\n DocumentChangeEvent?: DocumentChangeEventResolvers<ContextType>;\n DocumentModelGlobalState?: DocumentModelGlobalStateResolvers<ContextType>;\n DocumentModelResultPage?: DocumentModelResultPageResolvers<ContextType>;\n DocumentRelationship?: DocumentRelationshipResolvers<ContextType>;\n DocumentRelationshipResultPage?: DocumentRelationshipResultPageResolvers<ContextType>;\n DocumentWithChildren?: DocumentWithChildrenResolvers<ContextType>;\n JSONObject?: GraphQLScalarType;\n JobChangeEvent?: JobChangeEventResolvers<ContextType>;\n JobInfo?: JobInfoResolvers<ContextType>;\n MoveRelationshipResult?: MoveRelationshipResultResolvers<ContextType>;\n Mutation?: MutationResolvers<ContextType>;\n OperationContext?: OperationContextResolvers<ContextType>;\n OperationWithContext?: OperationWithContextResolvers<ContextType>;\n PHDocument?: PhDocumentResolvers<ContextType>;\n PHDocumentResultPage?: PhDocumentResultPageResolvers<ContextType>;\n PollSyncEnvelopesResult?: PollSyncEnvelopesResultResolvers<ContextType>;\n Query?: QueryResolvers<ContextType>;\n ReactorOperation?: ReactorOperationResolvers<ContextType>;\n ReactorOperationResultPage?: ReactorOperationResultPageResolvers<ContextType>;\n ReactorSigner?: ReactorSignerResolvers<ContextType>;\n ReactorSignerApp?: ReactorSignerAppResolvers<ContextType>;\n ReactorSignerUser?: ReactorSignerUserResolvers<ContextType>;\n RemoteCursor?: RemoteCursorResolvers<ContextType>;\n Revision?: RevisionResolvers<ContextType>;\n Subscription?: SubscriptionResolvers<ContextType>;\n SyncEnvelope?: SyncEnvelopeResolvers<ContextType>;\n TouchChannelResult?: TouchChannelResultResolvers<ContextType>;\n}>;\n\ntype Properties<T> = Required<{\n [K in keyof T]: z.ZodType<T[K]>;\n}>;\n\ntype definedNonNullAny = {};\n\nexport const isDefinedNonNullAny = (v: any): v is definedNonNullAny =>\n v !== undefined && v !== null;\n\nexport const definedNonNullAnySchema = z\n .any()\n .refine((v) => isDefinedNonNullAny(v));\n\nexport const AuthDecisionSchema = z.enum(AuthDecision);\n\nexport const DocumentChangeTypeSchema = z.enum(DocumentChangeType);\n\nexport const PropagationModeSchema = z.enum(PropagationMode);\n\nexport const SyncEnvelopeTypeSchema = z.enum(SyncEnvelopeType);\n\nexport function ActionCandidateInputSchema(): z.ZodObject<\n Properties<ActionCandidateInput>\n> {\n return z.object({\n input: z.custom<NonNullable<unknown>>((v) => v != null).nullish(),\n scope: z.string(),\n type: z.string(),\n });\n}\n\nexport function ActionContextInputSchema(): z.ZodObject<\n Properties<ActionContextInput>\n> {\n return z.object({\n nonce: z.string().nullish(),\n prevOpHash: z.string().nullish(),\n prevOpIndex: z.number().nullish(),\n signer: z.lazy(() => ReactorSignerInputSchema().nullish()),\n });\n}\n\nexport function ActionInputSchema(): z.ZodObject<Properties<ActionInput>> {\n return z.object({\n context: z.lazy(() => ActionContextInputSchema().nullish()),\n id: z.string(),\n input: z.custom<NonNullable<unknown>>((v) => v != null),\n scope: z.string(),\n timestampUtcMs: z.string(),\n type: z.string(),\n });\n}\n\nexport function ChannelMetaInputSchema(): z.ZodObject<\n Properties<ChannelMetaInput>\n> {\n return z.object({\n id: z.string(),\n });\n}\n\nexport function DocumentOperationsFilterInputSchema(): z.ZodObject<\n Properties<DocumentOperationsFilterInput>\n> {\n return z.object({\n actionTypes: z.array(z.string()).nullish(),\n branch: z.string().nullish(),\n scopes: z.array(z.string()).nullish(),\n sinceRevision: z.number().nullish(),\n timestampFrom: z.string().nullish(),\n timestampTo: z.string().nullish(),\n });\n}\n\nexport function OperationContextInputSchema(): z.ZodObject<\n Properties<OperationContextInput>\n> {\n return z.object({\n branch: z.string(),\n documentId: z.string(),\n documentType: z.string(),\n ordinal: z.number(),\n scope: z.string(),\n });\n}\n\nexport function OperationInputSchema(): z.ZodObject<\n Properties<OperationInput>\n> {\n return z.object({\n action: z.lazy(() => ActionInputSchema()),\n deniedReason: z.string().nullish(),\n error: z.string().nullish(),\n hash: z.string(),\n id: z.string().nullish(),\n index: z.number(),\n skip: z.number(),\n timestampUtcMs: z.string(),\n });\n}\n\nexport function OperationWithContextInputSchema(): z.ZodObject<\n Properties<OperationWithContextInput>\n> {\n return z.object({\n context: z.lazy(() => OperationContextInputSchema()),\n operation: z.lazy(() => OperationInputSchema()),\n });\n}\n\nexport function OperationsFilterInputSchema(): z.ZodObject<\n Properties<OperationsFilterInput>\n> {\n return z.object({\n actionTypes: z.array(z.string()).nullish(),\n branch: z.string().nullish(),\n documentId: z.string(),\n scopes: z.array(z.string()).nullish(),\n sinceRevision: z.number().nullish(),\n timestampFrom: z.string().nullish(),\n timestampTo: z.string().nullish(),\n });\n}\n\nexport function PagingInputSchema(): z.ZodObject<Properties<PagingInput>> {\n return z.object({\n cursor: z.string().nullish(),\n limit: z.number().nullish(),\n offset: z.number().nullish(),\n });\n}\n\nexport function ReactorSignerAppInputSchema(): z.ZodObject<\n Properties<ReactorSignerAppInput>\n> {\n return z.object({\n key: z.string(),\n name: z.string(),\n });\n}\n\nexport function ReactorSignerInputSchema(): z.ZodObject<\n Properties<ReactorSignerInput>\n> {\n return z.object({\n app: z.lazy(() => ReactorSignerAppInputSchema().nullish()),\n signatures: z.array(z.string()),\n user: z.lazy(() => ReactorSignerUserInputSchema().nullish()),\n });\n}\n\nexport function ReactorSignerUserInputSchema(): z.ZodObject<\n Properties<ReactorSignerUserInput>\n> {\n return z.object({\n address: z.string(),\n chainId: z.number(),\n networkId: z.string(),\n });\n}\n\nexport function RemoteCursorInputSchema(): z.ZodObject<\n Properties<RemoteCursorInput>\n> {\n return z.object({\n cursorOrdinal: z.number(),\n lastSyncedAtUtcMs: z.string().nullish(),\n remoteName: z.string(),\n });\n}\n\nexport function RemoteFilterInputSchema(): z.ZodObject<\n Properties<RemoteFilterInput>\n> {\n return z.object({\n branch: z.string(),\n documentId: z.array(z.string()),\n scope: z.array(z.string()),\n });\n}\n\nexport function SearchFilterInputSchema(): z.ZodObject<\n Properties<SearchFilterInput>\n> {\n return z.object({\n identifiers: z.array(z.string()).nullish(),\n parentId: z.string().nullish(),\n type: z.string().nullish(),\n });\n}\n\nexport function SyncEnvelopeInputSchema(): z.ZodObject<\n Properties<SyncEnvelopeInput>\n> {\n return z.object({\n channelMeta: z.lazy(() => ChannelMetaInputSchema()),\n cursor: z.lazy(() => RemoteCursorInputSchema().nullish()),\n dependsOn: z.array(z.string()).nullish(),\n key: z.string().nullish(),\n operations: z\n .array(z.lazy(() => OperationWithContextInputSchema()))\n .nullish(),\n type: SyncEnvelopeTypeSchema,\n });\n}\n\nexport function TouchChannelInputSchema(): z.ZodObject<\n Properties<TouchChannelInput>\n> {\n return z.object({\n collectionId: z.string(),\n filter: z.lazy(() => RemoteFilterInputSchema()),\n id: z.string(),\n name: z.string(),\n sinceTimestampUtcMs: z.string(),\n });\n}\n\nexport function ViewFilterInputSchema(): z.ZodObject<\n Properties<ViewFilterInput>\n> {\n return z.object({\n branch: z.string().nullish(),\n scopes: z.array(z.string()).nullish(),\n });\n}\n\nexport const PhDocumentFieldsFragmentDoc = gql`\n fragment PHDocumentFields on PHDocument {\n id\n slug\n name\n documentType\n state\n revisionsList {\n scope\n revision\n }\n createdAtUtcIso\n lastModifiedAtUtcIso\n }\n`;\nexport const DocumentRelationshipFieldsFragmentDoc = gql`\n fragment DocumentRelationshipFields on DocumentRelationship {\n sourceId\n targetId\n relationshipType\n metadata\n createdAt\n updatedAt\n }\n`;\nexport const GetDocumentModelsDocument = gql`\n query GetDocumentModels($namespace: String, $paging: PagingInput) {\n documentModels(namespace: $namespace, paging: $paging) {\n items {\n id\n name\n namespace\n version\n specification\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n`;\nexport const GetDocumentDocument = gql`\n query GetDocument($identifier: String!, $view: ViewFilterInput) {\n document(identifier: $identifier, view: $view) {\n document {\n ...PHDocumentFields\n }\n childIds\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const GetDocumentWithOperationsDocument = gql`\n query GetDocumentWithOperations(\n $identifier: String!\n $view: ViewFilterInput\n $operationsFilter: DocumentOperationsFilterInput\n $operationsPaging: PagingInput\n ) {\n document(identifier: $identifier, view: $view) {\n document {\n ...PHDocumentFields\n operations(filter: $operationsFilter, paging: $operationsPaging) {\n items {\n index\n timestampUtcMs\n hash\n skip\n error\n deniedReason\n id\n action {\n id\n type\n timestampUtcMs\n input\n scope\n context {\n signer {\n user {\n address\n networkId\n chainId\n }\n app {\n name\n key\n }\n signatures\n }\n }\n }\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n childIds\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const GetDocumentOutgoingRelationshipsDocument = gql`\n query GetDocumentOutgoingRelationships(\n $sourceIdentifier: String!\n $relationshipType: String!\n $view: ViewFilterInput\n $paging: PagingInput\n ) {\n documentOutgoingRelationships(\n sourceIdentifier: $sourceIdentifier\n relationshipType: $relationshipType\n view: $view\n paging: $paging\n ) {\n items {\n ...PHDocumentFields\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const GetDocumentIncomingRelationshipsDocument = gql`\n query GetDocumentIncomingRelationships(\n $targetIdentifier: String!\n $relationshipType: String!\n $view: ViewFilterInput\n $paging: PagingInput\n ) {\n documentIncomingRelationships(\n targetIdentifier: $targetIdentifier\n relationshipType: $relationshipType\n view: $view\n paging: $paging\n ) {\n items {\n ...PHDocumentFields\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const GetDocumentOutgoingRelationshipEdgesDocument = gql`\n query GetDocumentOutgoingRelationshipEdges(\n $sourceIdentifier: String!\n $relationshipType: String\n $view: ViewFilterInput\n $paging: PagingInput\n ) {\n documentOutgoingRelationshipEdges(\n sourceIdentifier: $sourceIdentifier\n relationshipType: $relationshipType\n view: $view\n paging: $paging\n ) {\n items {\n ...DocumentRelationshipFields\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n ${DocumentRelationshipFieldsFragmentDoc}\n`;\nexport const GetDocumentIncomingRelationshipEdgesDocument = gql`\n query GetDocumentIncomingRelationshipEdges(\n $targetIdentifier: String!\n $relationshipType: String\n $view: ViewFilterInput\n $paging: PagingInput\n ) {\n documentIncomingRelationshipEdges(\n targetIdentifier: $targetIdentifier\n relationshipType: $relationshipType\n view: $view\n paging: $paging\n ) {\n items {\n ...DocumentRelationshipFields\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n ${DocumentRelationshipFieldsFragmentDoc}\n`;\nexport const FindDocumentsDocument = gql`\n query FindDocuments(\n $search: SearchFilterInput\n $view: ViewFilterInput\n $paging: PagingInput\n ) {\n findDocuments(search: $search, view: $view, paging: $paging) {\n items {\n ...PHDocumentFields\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const GetDocumentOperationsDocument = gql`\n query GetDocumentOperations(\n $filter: OperationsFilterInput!\n $paging: PagingInput\n ) {\n documentOperations(filter: $filter, paging: $paging) {\n items {\n index\n timestampUtcMs\n hash\n skip\n error\n deniedReason\n id\n action {\n id\n type\n timestampUtcMs\n input\n scope\n context {\n signer {\n user {\n address\n networkId\n chainId\n }\n app {\n name\n key\n }\n signatures\n }\n }\n }\n }\n hasNextPage\n hasPreviousPage\n cursor\n }\n }\n`;\nexport const GetJobStatusDocument = gql`\n query GetJobStatus($jobId: String!) {\n jobStatus(jobId: $jobId) {\n id\n status\n result\n error\n createdAt\n completedAt\n }\n }\n`;\nexport const EvaluateActionsDocument = gql`\n query EvaluateActions(\n $documentIdentifier: String!\n $branch: String\n $candidates: [ActionCandidateInput!]!\n ) {\n evaluateActions(\n documentIdentifier: $documentIdentifier\n branch: $branch\n candidates: $candidates\n ) {\n evaluations {\n decision\n reason\n }\n allAllowed\n anyAllowed\n allDenied\n anyDenied\n }\n }\n`;\nexport const CreateDocumentDocument = gql`\n mutation CreateDocument($document: JSONObject!, $parentIdentifier: String) {\n createDocument(document: $document, parentIdentifier: $parentIdentifier) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const CreateEmptyDocumentDocument = gql`\n mutation CreateEmptyDocument(\n $documentType: String!\n $parentIdentifier: String\n ) {\n createEmptyDocument(\n documentType: $documentType\n parentIdentifier: $parentIdentifier\n ) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const MutateDocumentDocument = gql`\n mutation MutateDocument(\n $documentIdentifier: String!\n $actions: [ActionInput!]!\n $branch: String\n ) {\n mutateDocument: execute(\n documentIdentifier: $documentIdentifier\n actions: $actions\n branch: $branch\n ) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const MutateDocumentAsyncDocument = gql`\n mutation MutateDocumentAsync(\n $documentIdentifier: String!\n $actions: [ActionInput!]!\n $branch: String\n ) {\n mutateDocumentAsync: executeAsync(\n documentIdentifier: $documentIdentifier\n actions: $actions\n branch: $branch\n ) {\n id\n status\n result\n error\n createdAt\n completedAt\n }\n }\n`;\nexport const RenameDocumentDocument = gql`\n mutation RenameDocument(\n $documentIdentifier: String!\n $name: String!\n $branch: String\n ) {\n renameDocument(\n documentIdentifier: $documentIdentifier\n name: $name\n branch: $branch\n ) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const SetPreferredEditorDocument = gql`\n mutation SetPreferredEditor(\n $documentIdentifier: String!\n $preferredEditor: String\n $branch: String\n ) {\n setPreferredEditor(\n documentIdentifier: $documentIdentifier\n preferredEditor: $preferredEditor\n branch: $branch\n ) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const AddRelationshipDocument = gql`\n mutation AddRelationship(\n $sourceIdentifier: String!\n $targetIdentifier: String!\n $relationshipType: String!\n $metadata: JSONObject\n $branch: String\n ) {\n addRelationship(\n sourceIdentifier: $sourceIdentifier\n targetIdentifier: $targetIdentifier\n relationshipType: $relationshipType\n metadata: $metadata\n branch: $branch\n ) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const UpdateRelationshipDocument = gql`\n mutation UpdateRelationship(\n $sourceIdentifier: String!\n $targetIdentifier: String!\n $relationshipType: String!\n $metadata: JSONObject\n $branch: String\n ) {\n updateRelationship(\n sourceIdentifier: $sourceIdentifier\n targetIdentifier: $targetIdentifier\n relationshipType: $relationshipType\n metadata: $metadata\n branch: $branch\n ) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const RemoveRelationshipDocument = gql`\n mutation RemoveRelationship(\n $sourceIdentifier: String!\n $targetIdentifier: String!\n $relationshipType: String!\n $branch: String\n ) {\n removeRelationship(\n sourceIdentifier: $sourceIdentifier\n targetIdentifier: $targetIdentifier\n relationshipType: $relationshipType\n branch: $branch\n ) {\n ...PHDocumentFields\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const MoveRelationshipDocument = gql`\n mutation MoveRelationship(\n $sourceParentIdentifier: String!\n $targetParentIdentifier: String!\n $targetIdentifier: String!\n $relationshipType: String!\n $branch: String\n ) {\n moveRelationship(\n sourceParentIdentifier: $sourceParentIdentifier\n targetParentIdentifier: $targetParentIdentifier\n targetIdentifier: $targetIdentifier\n relationshipType: $relationshipType\n branch: $branch\n ) {\n source {\n ...PHDocumentFields\n }\n target {\n ...PHDocumentFields\n }\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const DeleteDocumentDocument = gql`\n mutation DeleteDocument($identifier: String!, $propagate: PropagationMode) {\n deleteDocument(identifier: $identifier, propagate: $propagate)\n }\n`;\nexport const DeleteDocumentsDocument = gql`\n mutation DeleteDocuments(\n $identifiers: [String!]!\n $propagate: PropagationMode\n ) {\n deleteDocuments(identifiers: $identifiers, propagate: $propagate)\n }\n`;\nexport const DocumentChangesDocument = gql`\n subscription DocumentChanges(\n $search: SearchFilterInput\n $view: ViewFilterInput\n ) {\n documentChanges(search: $search, view: $view) {\n type\n documents {\n ...PHDocumentFields\n }\n context {\n parentId\n childId\n }\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n`;\nexport const JobChangesDocument = gql`\n subscription JobChanges($jobId: String!) {\n jobChanges(jobId: $jobId) {\n jobId\n status\n result\n error\n }\n }\n`;\nexport const PollSyncEnvelopesDocument = gql`\n query PollSyncEnvelopes(\n $channelId: String!\n $outboxAck: Int!\n $outboxLatest: Int!\n ) {\n pollSyncEnvelopes(\n channelId: $channelId\n outboxAck: $outboxAck\n outboxLatest: $outboxLatest\n ) {\n envelopes {\n type\n channelMeta {\n id\n }\n operations {\n operation {\n index\n timestampUtcMs\n hash\n skip\n error\n deniedReason\n id\n action {\n id\n type\n timestampUtcMs\n input\n scope\n context {\n signer {\n user {\n address\n networkId\n chainId\n }\n app {\n name\n key\n }\n signatures\n }\n }\n }\n }\n context {\n documentId\n documentType\n scope\n branch\n }\n }\n cursor {\n remoteName\n cursorOrdinal\n lastSyncedAtUtcMs\n }\n key\n dependsOn\n }\n ackOrdinal\n deadLetters {\n documentId\n error\n errorType\n }\n hasMore\n }\n }\n`;\nexport const TouchChannelDocument = gql`\n mutation TouchChannel($input: TouchChannelInput!) {\n touchChannel(input: $input) {\n success\n ackOrdinal\n }\n }\n`;\nexport const PushSyncEnvelopesDocument = gql`\n mutation PushSyncEnvelopes($envelopes: [SyncEnvelopeInput!]!) {\n pushSyncEnvelopes(envelopes: $envelopes)\n }\n`;\nexport type Requester<C = {}> = <R, V>(\n doc: DocumentNode,\n vars?: V,\n options?: C,\n) => Promise<R> | AsyncIterable<R>;\nexport function getSdk<C>(requester: Requester<C>) {\n return {\n GetDocumentModels(\n variables?: GetDocumentModelsQueryVariables,\n options?: C,\n ): Promise<GetDocumentModelsQuery> {\n return requester<GetDocumentModelsQuery, GetDocumentModelsQueryVariables>(\n GetDocumentModelsDocument,\n variables,\n options,\n ) as Promise<GetDocumentModelsQuery>;\n },\n GetDocument(\n variables: GetDocumentQueryVariables,\n options?: C,\n ): Promise<GetDocumentQuery> {\n return requester<GetDocumentQuery, GetDocumentQueryVariables>(\n GetDocumentDocument,\n variables,\n options,\n ) as Promise<GetDocumentQuery>;\n },\n GetDocumentWithOperations(\n variables: GetDocumentWithOperationsQueryVariables,\n options?: C,\n ): Promise<GetDocumentWithOperationsQuery> {\n return requester<\n GetDocumentWithOperationsQuery,\n GetDocumentWithOperationsQueryVariables\n >(\n GetDocumentWithOperationsDocument,\n variables,\n options,\n ) as Promise<GetDocumentWithOperationsQuery>;\n },\n GetDocumentOutgoingRelationships(\n variables: GetDocumentOutgoingRelationshipsQueryVariables,\n options?: C,\n ): Promise<GetDocumentOutgoingRelationshipsQuery> {\n return requester<\n GetDocumentOutgoingRelationshipsQuery,\n GetDocumentOutgoingRelationshipsQueryVariables\n >(\n GetDocumentOutgoingRelationshipsDocument,\n variables,\n options,\n ) as Promise<GetDocumentOutgoingRelationshipsQuery>;\n },\n GetDocumentIncomingRelationships(\n variables: GetDocumentIncomingRelationshipsQueryVariables,\n options?: C,\n ): Promise<GetDocumentIncomingRelationshipsQuery> {\n return requester<\n GetDocumentIncomingRelationshipsQuery,\n GetDocumentIncomingRelationshipsQueryVariables\n >(\n GetDocumentIncomingRelationshipsDocument,\n variables,\n options,\n ) as Promise<GetDocumentIncomingRelationshipsQuery>;\n },\n GetDocumentOutgoingRelationshipEdges(\n variables: GetDocumentOutgoingRelationshipEdgesQueryVariables,\n options?: C,\n ): Promise<GetDocumentOutgoingRelationshipEdgesQuery> {\n return requester<\n GetDocumentOutgoingRelationshipEdgesQuery,\n GetDocumentOutgoingRelationshipEdgesQueryVariables\n >(\n GetDocumentOutgoingRelationshipEdgesDocument,\n variables,\n options,\n ) as Promise<GetDocumentOutgoingRelationshipEdgesQuery>;\n },\n GetDocumentIncomingRelationshipEdges(\n variables: GetDocumentIncomingRelationshipEdgesQueryVariables,\n options?: C,\n ): Promise<GetDocumentIncomingRelationshipEdgesQuery> {\n return requester<\n GetDocumentIncomingRelationshipEdgesQuery,\n GetDocumentIncomingRelationshipEdgesQueryVariables\n >(\n GetDocumentIncomingRelationshipEdgesDocument,\n variables,\n options,\n ) as Promise<GetDocumentIncomingRelationshipEdgesQuery>;\n },\n FindDocuments(\n variables?: FindDocumentsQueryVariables,\n options?: C,\n ): Promise<FindDocumentsQuery> {\n return requester<FindDocumentsQuery, FindDocumentsQueryVariables>(\n FindDocumentsDocument,\n variables,\n options,\n ) as Promise<FindDocumentsQuery>;\n },\n GetDocumentOperations(\n variables: GetDocumentOperationsQueryVariables,\n options?: C,\n ): Promise<GetDocumentOperationsQuery> {\n return requester<\n GetDocumentOperationsQuery,\n GetDocumentOperationsQueryVariables\n >(\n GetDocumentOperationsDocument,\n variables,\n options,\n ) as Promise<GetDocumentOperationsQuery>;\n },\n GetJobStatus(\n variables: GetJobStatusQueryVariables,\n options?: C,\n ): Promise<GetJobStatusQuery> {\n return requester<GetJobStatusQuery, GetJobStatusQueryVariables>(\n GetJobStatusDocument,\n variables,\n options,\n ) as Promise<GetJobStatusQuery>;\n },\n EvaluateActions(\n variables: EvaluateActionsQueryVariables,\n options?: C,\n ): Promise<EvaluateActionsQuery> {\n return requester<EvaluateActionsQuery, EvaluateActionsQueryVariables>(\n EvaluateActionsDocument,\n variables,\n options,\n ) as Promise<EvaluateActionsQuery>;\n },\n CreateDocument(\n variables: CreateDocumentMutationVariables,\n options?: C,\n ): Promise<CreateDocumentMutation> {\n return requester<CreateDocumentMutation, CreateDocumentMutationVariables>(\n CreateDocumentDocument,\n variables,\n options,\n ) as Promise<CreateDocumentMutation>;\n },\n CreateEmptyDocument(\n variables: CreateEmptyDocumentMutationVariables,\n options?: C,\n ): Promise<CreateEmptyDocumentMutation> {\n return requester<\n CreateEmptyDocumentMutation,\n CreateEmptyDocumentMutationVariables\n >(\n CreateEmptyDocumentDocument,\n variables,\n options,\n ) as Promise<CreateEmptyDocumentMutation>;\n },\n MutateDocument(\n variables: MutateDocumentMutationVariables,\n options?: C,\n ): Promise<MutateDocumentMutation> {\n return requester<MutateDocumentMutation, MutateDocumentMutationVariables>(\n MutateDocumentDocument,\n variables,\n options,\n ) as Promise<MutateDocumentMutation>;\n },\n MutateDocumentAsync(\n variables: MutateDocumentAsyncMutationVariables,\n options?: C,\n ): Promise<MutateDocumentAsyncMutation> {\n return requester<\n MutateDocumentAsyncMutation,\n MutateDocumentAsyncMutationVariables\n >(\n MutateDocumentAsyncDocument,\n variables,\n options,\n ) as Promise<MutateDocumentAsyncMutation>;\n },\n RenameDocument(\n variables: RenameDocumentMutationVariables,\n options?: C,\n ): Promise<RenameDocumentMutation> {\n return requester<RenameDocumentMutation, RenameDocumentMutationVariables>(\n RenameDocumentDocument,\n variables,\n options,\n ) as Promise<RenameDocumentMutation>;\n },\n SetPreferredEditor(\n variables: SetPreferredEditorMutationVariables,\n options?: C,\n ): Promise<SetPreferredEditorMutation> {\n return requester<\n SetPreferredEditorMutation,\n SetPreferredEditorMutationVariables\n >(\n SetPreferredEditorDocument,\n variables,\n options,\n ) as Promise<SetPreferredEditorMutation>;\n },\n AddRelationship(\n variables: AddRelationshipMutationVariables,\n options?: C,\n ): Promise<AddRelationshipMutation> {\n return requester<\n AddRelationshipMutation,\n AddRelationshipMutationVariables\n >(\n AddRelationshipDocument,\n variables,\n options,\n ) as Promise<AddRelationshipMutation>;\n },\n UpdateRelationship(\n variables: UpdateRelationshipMutationVariables,\n options?: C,\n ): Promise<UpdateRelationshipMutation> {\n return requester<\n UpdateRelationshipMutation,\n UpdateRelationshipMutationVariables\n >(\n UpdateRelationshipDocument,\n variables,\n options,\n ) as Promise<UpdateRelationshipMutation>;\n },\n RemoveRelationship(\n variables: RemoveRelationshipMutationVariables,\n options?: C,\n ): Promise<RemoveRelationshipMutation> {\n return requester<\n RemoveRelationshipMutation,\n RemoveRelationshipMutationVariables\n >(\n RemoveRelationshipDocument,\n variables,\n options,\n ) as Promise<RemoveRelationshipMutation>;\n },\n MoveRelationship(\n variables: MoveRelationshipMutationVariables,\n options?: C,\n ): Promise<MoveRelationshipMutation> {\n return requester<\n MoveRelationshipMutation,\n MoveRelationshipMutationVariables\n >(\n MoveRelationshipDocument,\n variables,\n options,\n ) as Promise<MoveRelationshipMutation>;\n },\n DeleteDocument(\n variables: DeleteDocumentMutationVariables,\n options?: C,\n ): Promise<DeleteDocumentMutation> {\n return requester<DeleteDocumentMutation, DeleteDocumentMutationVariables>(\n DeleteDocumentDocument,\n variables,\n options,\n ) as Promise<DeleteDocumentMutation>;\n },\n DeleteDocuments(\n variables: DeleteDocumentsMutationVariables,\n options?: C,\n ): Promise<DeleteDocumentsMutation> {\n return requester<\n DeleteDocumentsMutation,\n DeleteDocumentsMutationVariables\n >(\n DeleteDocumentsDocument,\n variables,\n options,\n ) as Promise<DeleteDocumentsMutation>;\n },\n DocumentChanges(\n variables?: DocumentChangesSubscriptionVariables,\n options?: C,\n ): AsyncIterable<DocumentChangesSubscription> {\n return requester<\n DocumentChangesSubscription,\n DocumentChangesSubscriptionVariables\n >(\n DocumentChangesDocument,\n variables,\n options,\n ) as AsyncIterable<DocumentChangesSubscription>;\n },\n JobChanges(\n variables: JobChangesSubscriptionVariables,\n options?: C,\n ): AsyncIterable<JobChangesSubscription> {\n return requester<JobChangesSubscription, JobChangesSubscriptionVariables>(\n JobChangesDocument,\n variables,\n options,\n ) as AsyncIterable<JobChangesSubscription>;\n },\n PollSyncEnvelopes(\n variables: PollSyncEnvelopesQueryVariables,\n options?: C,\n ): Promise<PollSyncEnvelopesQuery> {\n return requester<PollSyncEnvelopesQuery, PollSyncEnvelopesQueryVariables>(\n PollSyncEnvelopesDocument,\n variables,\n options,\n ) as Promise<PollSyncEnvelopesQuery>;\n },\n TouchChannel(\n variables: TouchChannelMutationVariables,\n options?: C,\n ): Promise<TouchChannelMutation> {\n return requester<TouchChannelMutation, TouchChannelMutationVariables>(\n TouchChannelDocument,\n variables,\n options,\n ) as Promise<TouchChannelMutation>;\n },\n PushSyncEnvelopes(\n variables: PushSyncEnvelopesMutationVariables,\n options?: C,\n ): Promise<PushSyncEnvelopesMutation> {\n return requester<\n PushSyncEnvelopesMutation,\n PushSyncEnvelopesMutationVariables\n >(\n PushSyncEnvelopesDocument,\n variables,\n options,\n ) as Promise<PushSyncEnvelopesMutation>;\n },\n };\n}\nexport type Sdk = ReturnType<typeof getSdk>;\n","import {\n type JobInfo as ClientJobInfo,\n type DocumentChangeEvent,\n type DocumentRelationship,\n type Evaluation,\n type PagedResults,\n PropagationMode,\n} from \"@powerhousedao/reactor\";\nimport { camelCase } from \"change-case\";\nimport type {\n Action,\n ActionContext,\n ActionSigner,\n DocumentModelModule,\n DocumentModelPHState,\n Operation,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n deserializeSignature,\n serializeSignature,\n} from \"@powerhousedao/shared/document-model\";\nimport { GraphQLError } from \"graphql\";\nimport { MalformedStoredOperationError } from \"../errors.js\";\nimport {\n type ActionInput,\n type ActionEvaluation as GqlActionEvaluation,\n AuthDecision as GqlAuthDecision,\n type DocumentModelResultPage,\n type DocumentRelationship as GqlDocumentRelationship,\n type DocumentRelationshipResultPage as GqlDocumentRelationshipResultPage,\n type DocumentChangeEvent as GqlDocumentChangeEvent,\n type DocumentModelGlobalState as GqlDocumentModelGlobalState,\n type JobInfo as GqlJobInfo,\n type PhDocument,\n type PhDocumentResultPage,\n PropagationMode as GqlPropagationMode,\n type ReactorOperation,\n type ReactorOperationResultPage,\n} from \"./gen/graphql.js\";\n\n/**\n * Converts a PagedResults from ReactorClient to the GraphQL DocumentModelResultPage format\n */\nexport function toDocumentModelResultPage(\n result: PagedResults<DocumentModelModule>,\n): DocumentModelResultPage {\n const models = result.results.map((module) => module.documentModel);\n return {\n cursor: result.nextCursor ?? null,\n hasNextPage: !!result.nextCursor,\n hasPreviousPage: !!result.options.cursor,\n items: models.map(toGqlDocumentModelState),\n };\n}\n\n/**\n * Gets the namespace from a DocumentModelGlobalState\n */\nfunction getNamespace(model: DocumentModelPHState): string {\n return model.global.name.split(\"/\")[0];\n}\n\n/**\n * Converts a DocumentModelGlobalState from ReactorClient to GraphQL format\n */\nfunction toGqlDocumentModelState(\n model: DocumentModelPHState,\n): GqlDocumentModelGlobalState {\n const global = model.global;\n const specification =\n global.specifications.length > 0 ? global.specifications[0] : {};\n const namespace = getNamespace(model);\n\n return {\n id: global.id,\n name: global.name,\n namespace,\n specification,\n version: null,\n };\n}\n\n/**\n * Converts a PagedResults of PHDocument to GraphQL PhDocumentResultPage format\n */\nexport function toPhDocumentResultPage(\n result: PagedResults<PHDocument>,\n): PhDocumentResultPage {\n return {\n cursor: result.nextCursor ?? null,\n hasNextPage: !!result.nextCursor,\n hasPreviousPage: !!result.options.cursor,\n items: result.results.map(toGqlPhDocument),\n };\n}\n\n/**\n * Converts a relationship edge from the indexer to GraphQL format.\n */\nexport function toGqlDocumentRelationship(\n relationship: DocumentRelationship,\n): GqlDocumentRelationship {\n return {\n sourceId: relationship.sourceId,\n targetId: relationship.targetId,\n relationshipType: relationship.relationshipType,\n metadata: relationship.metadata ?? null,\n createdAt: relationship.createdAt,\n updatedAt: relationship.updatedAt,\n };\n}\n\n/**\n * Converts a PagedResults of relationship edges to GraphQL\n * DocumentRelationshipResultPage format\n */\nexport function toDocumentRelationshipResultPage(\n result: PagedResults<DocumentRelationship>,\n): GqlDocumentRelationshipResultPage {\n return {\n cursor: result.nextCursor ?? null,\n hasNextPage: !!result.nextCursor,\n hasPreviousPage: !!result.options.cursor,\n items: result.results.map(toGqlDocumentRelationship),\n };\n}\n\n/**\n * Converts a PHDocument from ReactorClient to GraphQL PhDocument format\n */\nexport function toGqlPhDocument(doc: PHDocument): PhDocument {\n const revisionsList = Object.entries(doc.header.revision).map(\n ([scope, revision]) => ({\n scope,\n revision,\n }),\n );\n\n return {\n id: doc.header.id,\n name: doc.header.name,\n documentType: doc.header.documentType,\n slug: doc.header.slug,\n preferredEditor: doc.header.meta?.preferredEditor ?? null,\n createdAtUtcIso: doc.header.createdAtUtcIso,\n lastModifiedAtUtcIso: doc.header.lastModifiedAtUtcIso,\n revisionsList,\n state: doc.state,\n };\n}\n\n/**\n * Converts JobInfo from ReactorClient to GraphQL format\n */\nexport function toGqlJobInfo(job: ClientJobInfo): GqlJobInfo {\n return {\n id: job.id,\n status: job.status,\n createdAt: job.createdAtUtcIso,\n completedAt: job.completedAtUtcIso ?? null,\n error: job.error?.message ?? null,\n result: job.result ?? null,\n };\n}\n\n/**\n * Handles nullable/undefined conversion for GraphQL InputMaybe types\n */\nexport function fromInputMaybe<T>(value: T | null | undefined): T | undefined {\n return value === null ? undefined : value;\n}\n\n/**\n * Maps GraphQL PropagationMode enum to reactor PropagationMode enum.\n * The GQL enum uses uppercase values (\"CASCADE\") while the reactor\n * enum uses lowercase values (\"cascade\").\n */\nexport function toReactorPropagationMode(\n gqlMode: GqlPropagationMode | null | undefined,\n): PropagationMode | undefined {\n if (gqlMode == null) {\n return undefined;\n }\n switch (gqlMode) {\n case GqlPropagationMode.Cascade:\n return PropagationMode.Cascade;\n case GqlPropagationMode.Orphan:\n return PropagationMode.None;\n }\n}\n\n/**\n * Maps one predicted verdict to its GraphQL shape. A refusal's reason is the\n * consensus string the reactor would record for it, carried through verbatim so\n * a client can tell a deletion refusal from a missing grant; an allow has none.\n */\nexport function toGqlActionEvaluation(\n evaluation: Evaluation,\n): GqlActionEvaluation {\n return evaluation.decision === \"allow\"\n ? { decision: GqlAuthDecision.Allow, reason: null }\n : { decision: GqlAuthDecision.Deny, reason: evaluation.reason };\n}\n\n/**\n * Converts readonly arrays to mutable arrays for ReactorClient\n */\nexport function toMutableArray<T>(\n arr: readonly T[] | undefined,\n): T[] | undefined {\n return arr ? [...arr] : undefined;\n}\n\n/**\n * Validates that an incoming value has the structure of an Action.\n *\n * This is the whole guard on the way in. `mutateDocument` takes untyped JSON, so\n * nothing has checked these fields before a resolver runs, and the id in\n * particular has to be checked here: it is hashed into the operation id and\n * replay dedupes by it, so an action without one is stored under an operation id\n * shared by every id-less operation on the same document, scope and branch.\n *\n * The storage constraint would refuse such a row anyway, but only after a job\n * has been enqueued and failed. Refusing here answers the caller instead.\n */\nfunction validateActionStructure(obj: unknown): obj is Action {\n if (!obj || typeof obj !== \"object\") {\n return false;\n }\n\n const action = obj as Record<string, unknown>;\n\n // Required fields\n if (typeof action.id !== \"string\" || !action.id) {\n return false;\n }\n\n if (typeof action.type !== \"string\" || !action.type) {\n return false;\n }\n\n if (typeof action.scope !== \"string\" || !action.scope) {\n return false;\n }\n\n if (typeof action.timestampUtcMs !== \"string\" || !action.timestampUtcMs) {\n return false;\n }\n\n // input can be anything (unknown)\n if (!(\"input\" in action)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Restores an action's signatures to the tuples verification reads.\n *\n * A signature is a five-param tuple, and GraphQL declares `signatures` as a\n * list of strings, so a client joins each one for transport. The sync path\n * already splits them on arrival; this is the same step for the mutation path,\n * which had none - an action submitted there kept whatever shape it arrived in,\n * so the same signature was persisted as a tuple or as one joined string\n * depending on which door it came through.\n *\n * A tuple passes through untouched, so an in-process caller handing over real\n * signatures is unaffected.\n */\nfunction withDeserializedSignatures(action: Action): Action {\n const signer = action.context?.signer;\n if (!signer?.signatures || signer.signatures.length === 0) {\n return action;\n }\n\n return {\n ...action,\n context: {\n ...action.context,\n signer: {\n ...signer,\n signatures: signer.signatures.map(deserializeSignature),\n },\n },\n };\n}\n\n/**\n * Converts actions the schema has already coerced into the actions the reactor\n * applies.\n *\n * The one conversion the schema cannot express is the signature: GraphQL\n * declares `signatures` as a list of strings, not of lists, so each arrives\n * joined and has to be read back as the tuple verification indexes into.\n *\n * Nothing is validated here. `ActionInput` states every field the reactor needs,\n * so anything that reached this point has them - unlike the untyped path, which\n * has to check by hand.\n */\nexport function toSubmittableActions(\n actions: readonly ActionInput[],\n): Action[] {\n return actions.map((action) => {\n const context = toSubmittableContext(action.context);\n const submittable: Action = {\n id: action.id,\n type: action.type,\n timestampUtcMs: action.timestampUtcMs,\n input: action.input,\n scope: action.scope,\n };\n return context ? { ...submittable, context } : submittable;\n });\n}\n\n/**\n * `ReactorSignerInput` leaves `user` and `app` optional where `ActionSigner`\n * requires them, so an incomplete signer cannot be represented. It is carried\n * through as it arrived rather than filled in: the signature verifier is what\n * should refuse it, and inventing either field here would be inventing the part\n * that says who signed.\n */\nfunction toSubmittableContext(\n context: ActionInput[\"context\"],\n): ActionContext | undefined {\n if (!context) {\n return undefined;\n }\n\n const submittable: ActionContext = {};\n const prevOpIndex = fromInputMaybe(context.prevOpIndex);\n if (prevOpIndex !== undefined) {\n submittable.prevOpIndex = prevOpIndex;\n }\n const prevOpHash = fromInputMaybe(context.prevOpHash);\n if (prevOpHash !== undefined) {\n submittable.prevOpHash = prevOpHash;\n }\n const nonce = fromInputMaybe(context.nonce);\n if (nonce !== undefined) {\n submittable.nonce = nonce;\n }\n\n const signer = fromInputMaybe(context.signer);\n if (signer) {\n submittable.signer = {\n user: fromInputMaybe(signer.user),\n app: fromInputMaybe(signer.app),\n signatures: signer.signatures.map(deserializeSignature),\n } as ActionSigner;\n }\n\n return Object.keys(submittable).length > 0 ? submittable : undefined;\n}\n\n/**\n * Converts a JSONObject to an Action, validating basic structure\n */\nexport function jsonObjectToAction(obj: unknown): Action {\n if (!validateActionStructure(obj)) {\n throw new GraphQLError(\n \"Invalid action structure. Actions must have: id (string), type (string), \" +\n \"scope (string), timestampUtcMs (string), and input (any)\",\n );\n }\n\n return withDeserializedSignatures(obj as Action);\n}\n\n/**\n * Validates an action against its document model\n * Based on validateDocumentModelAction from reactor-mcp\n */\nexport function validateDocumentModelAction(\n documentModelModule: DocumentModelModule,\n action: Action,\n): { isValid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n const globalState = documentModelModule.documentModel.global;\n\n // Get the latest specification\n if (!globalState.specifications || globalState.specifications.length === 0) {\n errors.push(\"Document model has no specifications\");\n return { isValid: false, errors };\n }\n\n const latestSpec =\n globalState.specifications[globalState.specifications.length - 1];\n\n // Search through modules to find the operation that matches the action type (in SCREAMING_SNAKE_CASE)\n let operation: (Operation & { scope: string }) | null = null;\n\n for (const module of latestSpec.modules) {\n const unsafeOperationOrActionOrSomething = module.operations.find(\n (op) => op.name === action.type,\n ) as unknown as Operation & { scope: string };\n if (unsafeOperationOrActionOrSomething) {\n operation = unsafeOperationOrActionOrSomething;\n break;\n }\n }\n\n if (!operation) {\n errors.push(\n `Operation \"${action.type}\" is not defined in any module of the document model`,\n );\n return { isValid: false, errors };\n }\n\n // Convert action type from SCREAMING_SNAKE_CASE to camelCase to match action creators\n const camelCaseActionType = camelCase(action.type);\n\n // Check if action creator exists in documentModelModule.actions\n const actionCreator = documentModelModule.actions[camelCaseActionType];\n\n if (!actionCreator) {\n errors.push(\n `Action creator \"${camelCaseActionType}\" for action type \"${action.type}\" is not defined in document model module actions`,\n );\n return { isValid: false, errors };\n }\n\n // Validate the operation using the action creator\n let inputError: Error | null = null;\n try {\n actionCreator(action.input);\n } catch (e) {\n inputError = e instanceof Error ? e : new Error(JSON.stringify(e));\n }\n\n if (inputError) {\n errors.push(`Input validation error: ${inputError.message}`);\n }\n\n // Validate scope if operation defines one\n if (operation.scope && action.scope !== operation.scope) {\n errors.push(\n `Action scope \"${action.scope}\" does not match operation scope \"${operation.scope}\"`,\n );\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * Validates a list of actions by converting them from JSON and checking structure\n */\nexport function validateActions(actions: readonly unknown[]): Action[] {\n const convertedActions: Action[] = [];\n for (let i = 0; i < actions.length; i++) {\n try {\n convertedActions.push(jsonObjectToAction(actions[i]));\n } catch (error) {\n throw new GraphQLError(\n `Action at index ${i}: ${error instanceof Error ? error.message : \"Invalid action structure\"}`,\n );\n }\n }\n return convertedActions;\n}\n\n/** The operation fields the schema declares non-null. */\nconst REQUIRED_OPERATION_FIELDS = [\n \"index\",\n \"timestampUtcMs\",\n \"hash\",\n \"skip\",\n] as const;\n\n/** The action fields the schema declares non-null. */\nconst REQUIRED_ACTION_FIELDS = [\n \"id\",\n \"type\",\n \"timestampUtcMs\",\n \"input\",\n \"scope\",\n] as const;\n\n/**\n * An operation as storage actually hands it over.\n *\n * `rowToOperation` casts a jsonb column straight to `Operation`, so every field\n * the declared type promises is present may be absent at runtime - that cast is\n * why TypeScript never caught this. Read through this view instead, or the\n * checks below look impossible to the compiler.\n */\ntype StoredOperation = Record<string, unknown> & {\n action?: Record<string, unknown> | null;\n};\n\n/**\n * Names an operation well enough to find the row it came from, without assuming\n * the fields that might be the missing ones.\n */\nfunction describeOperation(stored: StoredOperation): string {\n const parts = [\n typeof stored.id === \"string\" && stored.id\n ? `operation ${stored.id}`\n : \"operation with no id\",\n ];\n if (typeof stored.index === \"number\") {\n parts.push(`index ${stored.index}`);\n }\n const scope = stored.action?.scope;\n if (typeof scope === \"string\" && scope) {\n parts.push(`scope ${scope}`);\n }\n return parts.join(\", \");\n}\n\n/**\n * Refuses an operation the schema cannot represent, naming the field.\n *\n * The alternative is what execution does unaided: nullify the field, bubble that\n * up the non-null chain until it takes out the envelope's whole operation list,\n * and report a bare \"Cannot return null for non-nullable field\" with no way to\n * tell which of a hundred operations was at fault. Checked before the response\n * is built so the failure is typed and attributable.\n *\n * Presence is all that is checked. The schema's own serialization still rejects\n * a value of the wrong type, and inventing further rules here would put a second\n * contract beside the one the schema already states.\n */\nfunction assertServable(operation: Operation): void {\n const stored = operation as unknown as StoredOperation;\n\n for (const field of REQUIRED_OPERATION_FIELDS) {\n if (stored[field] === undefined || stored[field] === null) {\n throw new MalformedStoredOperationError(\n `${describeOperation(stored)} has no ${field}`,\n );\n }\n }\n\n const action = stored.action;\n if (action === undefined || action === null) {\n throw new MalformedStoredOperationError(\n `${describeOperation(stored)} has no action`,\n );\n }\n\n for (const field of REQUIRED_ACTION_FIELDS) {\n if (action[field] === undefined || action[field] === null) {\n throw new MalformedStoredOperationError(\n `${describeOperation(stored)} has an action with no ${field}`,\n );\n }\n }\n}\n\n/**\n * Transforms an operation to serialize signatures from tuples to strings for GraphQL compatibility.\n */\nexport function serializeOperationForGraphQL(\n operation: Operation,\n): ReactorOperation {\n assertServable(operation);\n\n const signer = operation.action.context?.signer;\n if (!signer?.signatures) {\n return operation as unknown as ReactorOperation;\n }\n\n return {\n ...operation,\n action: {\n ...operation.action,\n context: {\n ...operation.action.context,\n signer: {\n ...signer,\n signatures: signer.signatures.map(serializeSignature),\n },\n },\n },\n } as unknown as ReactorOperation;\n}\n\n/**\n * Converts a PagedResults of Operation to GraphQL ReactorOperationResultPage format\n */\nexport function toOperationResultPage(\n result: PagedResults<Operation>,\n): ReactorOperationResultPage {\n return {\n cursor: result.nextCursor ?? null,\n hasNextPage: !!result.nextCursor,\n hasPreviousPage: !!result.options.cursor && result.options.cursor !== \"0\",\n items: result.results.map(serializeOperationForGraphQL),\n };\n}\n\nexport function toGqlDocumentChangeEvent(\n event: DocumentChangeEvent,\n): GqlDocumentChangeEvent {\n const typeMap: Record<string, string> = {\n created: \"CREATED\",\n deleted: \"DELETED\",\n updated: \"UPDATED\",\n parent_added: \"PARENT_ADDED\",\n parent_removed: \"PARENT_REMOVED\",\n child_added: \"CHILD_ADDED\",\n child_removed: \"CHILD_REMOVED\",\n };\n\n const mappedType = typeMap[event.type];\n if (!mappedType) {\n throw new GraphQLError(`Unknown document change type: ${event.type}`);\n }\n\n return {\n type: mappedType as GqlDocumentChangeEvent[\"type\"],\n documents: event.documents.map(toGqlPhDocument),\n context: event.context\n ? {\n parentId: event.context.parentId ?? null,\n childId: event.context.childId ?? null,\n }\n : null,\n };\n}\n\n/**\n * Distinct document ids a change event references: affected documents plus the\n * parent/child ids in `context` (delete/relationship events carry only context).\n */\nexport function collectChangedDocumentIds(\n event: DocumentChangeEvent,\n): string[] {\n const ids = new Set<string>();\n for (const doc of event.documents) {\n if (doc.header.id) ids.add(doc.header.id);\n }\n if (event.context?.parentId) ids.add(event.context.parentId);\n if (event.context?.childId) ids.add(event.context.childId);\n return [...ids];\n}\n\nexport function matchesSearchFilter(\n event: DocumentChangeEvent,\n search: { type?: string | null; parentId?: string | null },\n): boolean {\n if (search.type) {\n const matchesType = event.documents.some(\n (doc) => doc.header.documentType === search.type,\n );\n if (!matchesType) {\n return false;\n }\n }\n\n if (search.parentId) {\n if (\n !event.context?.parentId ||\n event.context.parentId !== search.parentId\n ) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function matchesJobFilter(\n payload: { jobId: string },\n args: { jobId: string },\n): boolean {\n return payload.jobId === args.jobId;\n}\n","import { DEFAULT_DRIVE_CONTAINER_TYPES } from \"@powerhousedao/reactor\";\n\n/**\n * Legacy document-drive document type. Use {@link isDriveContainerType} for\n * drive-container gates; this constant is kept for places (e.g. legacy\n * default-drive bootstrap) that genuinely need the specific document-drive\n * type rather than \"any drive container\".\n */\nexport const DRIVE_DOCUMENT_TYPE = \"powerhouse/document-drive\";\n\n/**\n * Returns true when the given document type represents a drive container.\n * Delegates to the reactor's `DEFAULT_DRIVE_CONTAINER_TYPES`, so both the\n * legacy `powerhouse/document-drive` and the newer `powerhouse/reactor-drive`\n * count.\n */\nexport function isDriveContainerType(documentType: string): boolean {\n return DEFAULT_DRIVE_CONTAINER_TYPES.has(documentType);\n}\n","import {\n type ActionCandidate,\n type ActionEvaluations,\n AuthEnforcementDisabledError,\n consolidateSyncOperations,\n type DocumentRelationship,\n DriveCollectionId,\n envelopesToSyncOperations,\n type IDriveClient,\n type IReactorClient,\n type ISyncManager,\n type JobInfo,\n JobStatus,\n type OperationFilter,\n type PagedResults,\n type PagingOptions,\n type RemoteFilter,\n type SearchFilter,\n syncOperationErrorType,\n type SyncOperation,\n type SyncScopeGate,\n type ViewFilter,\n} from \"@powerhousedao/reactor\";\nimport type {\n AuthSubject,\n DocumentModelModule,\n Operation,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { withSignaturePolicy } from \"@powerhousedao/shared/document-model\";\nimport { GraphQLError } from \"graphql\";\n\nimport { AuthEvaluationUnsupportedError } from \"../errors.js\";\nimport { isDriveContainerType } from \"./constants.js\";\n\nconst REACTOR_DRIVE_DOCUMENT_TYPE = \"powerhouse/reactor-drive\";\n\n/**\n * Returns the drive client to use for the given drive-container parent type.\n * Throws when the parent is a reactor-drive container but no\n * `reactorDriveClient` was provided.\n */\nfunction pickDriveClient(\n reactorClient: IReactorClient,\n driveContainerType: string,\n reactorDriveClient: IDriveClient | undefined,\n): IDriveClient {\n if (driveContainerType === REACTOR_DRIVE_DOCUMENT_TYPE) {\n if (!reactorDriveClient) {\n throw new GraphQLError(\n \"Reactor-drive parent encountered but no reactorDriveClient is configured on this switchboard\",\n );\n }\n return reactorDriveClient;\n }\n return reactorClient.drives;\n}\n\n/**\n * A mutation's document re-read as the caller, since the client reads it back\n * as its signer. A caller who may write but not read gets it stripped.\n */\nasync function readAsCaller(\n reactorClient: IReactorClient,\n document: PHDocument,\n subject: AuthSubject | undefined,\n branch?: string,\n): Promise<PHDocument> {\n if (!subject) {\n return document;\n }\n try {\n return await reactorClient.get(document.header.id, { subject, branch });\n } catch (error) {\n throw new GraphQLError(\n `Failed to read the document back: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport const MAX_OPERATIONS_PER_ENVELOPE = 25;\nexport const MAX_OPERATIONS_PER_PAGE = 100;\nimport {\n fromInputMaybe,\n serializeOperationForGraphQL,\n toDocumentRelationshipResultPage,\n toGqlActionEvaluation,\n toDocumentModelResultPage,\n toGqlJobInfo,\n toSubmittableActions,\n toGqlPhDocument,\n toMutableArray,\n toOperationResultPage,\n toPhDocumentResultPage,\n toReactorPropagationMode,\n validateActions,\n} from \"./adapters.js\";\nimport type {\n ActionEvaluations as GqlActionEvaluations,\n ActionInput,\n DocumentModelResultPage,\n DocumentRelationshipResultPage,\n JobInfo as GqlJobInfo,\n PropagationMode as GqlPropagationMode,\n PhDocumentResultPage,\n ReactorOperationResultPage,\n} from \"./gen/graphql.js\";\n\nexport async function documentModels(\n reactorClient: IReactorClient,\n args: {\n namespace?: string | null;\n paging?: {\n cursor?: string | null;\n limit?: number | null;\n } | null;\n },\n): Promise<DocumentModelResultPage> {\n const namespace = fromInputMaybe(args.namespace);\n\n let paging: PagingOptions | undefined;\n if (args.paging) {\n const cursor = fromInputMaybe(args.paging.cursor);\n const limit = fromInputMaybe(args.paging.limit);\n if (cursor || limit) {\n paging = {\n cursor: cursor || \"\",\n limit: limit || 10,\n };\n }\n }\n\n let result: PagedResults<DocumentModelModule>;\n try {\n result = await reactorClient.getDocumentModelModules(namespace, paging);\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch document models: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toDocumentModelResultPage(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert document models to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function document(\n reactorClient: IReactorClient,\n args: {\n identifier: string;\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<{\n document: ReturnType<typeof toGqlPhDocument>;\n childIds: string[];\n}> {\n let view: ViewFilter | undefined = subject ? { subject } : undefined;\n if (args.view) {\n view = {\n subject,\n branch: fromInputMaybe(args.view.branch),\n scopes: toMutableArray(fromInputMaybe(args.view.scopes)),\n };\n }\n\n let result: PHDocument;\n try {\n result = await reactorClient.get(args.identifier, view);\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch document: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n let children: PagedResults<PHDocument>;\n try {\n children = await reactorClient.getOutgoingRelationships(\n args.identifier,\n \"child\",\n view,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch children: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return {\n document: toGqlPhDocument(result),\n childIds: children.results.map((child) => child.header.id),\n };\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function documentOutgoingRelationships(\n reactorClient: IReactorClient,\n args: {\n sourceIdentifier: string;\n relationshipType: string;\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n paging?: {\n cursor?: string | null;\n limit?: number | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<PhDocumentResultPage> {\n let view: ViewFilter | undefined = subject ? { subject } : undefined;\n if (args.view) {\n view = {\n subject,\n branch: fromInputMaybe(args.view.branch),\n scopes: toMutableArray(fromInputMaybe(args.view.scopes)),\n };\n }\n\n let paging: PagingOptions | undefined;\n if (args.paging) {\n const cursor = fromInputMaybe(args.paging.cursor);\n const limit = fromInputMaybe(args.paging.limit);\n if (cursor || limit) {\n paging = {\n cursor: cursor || \"\",\n limit: limit || 10,\n };\n }\n }\n\n let result: PagedResults<PHDocument>;\n try {\n result = await reactorClient.getOutgoingRelationships(\n args.sourceIdentifier,\n args.relationshipType,\n view,\n paging,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch outgoing relationships: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toPhDocumentResultPage(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert outgoing relationships to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function documentIncomingRelationships(\n reactorClient: IReactorClient,\n args: {\n targetIdentifier: string;\n relationshipType: string;\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n paging?: {\n cursor?: string | null;\n limit?: number | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<PhDocumentResultPage> {\n let view: ViewFilter | undefined = subject ? { subject } : undefined;\n if (args.view) {\n view = {\n subject,\n branch: fromInputMaybe(args.view.branch),\n scopes: toMutableArray(fromInputMaybe(args.view.scopes)),\n };\n }\n\n let paging: PagingOptions | undefined;\n if (args.paging) {\n const cursor = fromInputMaybe(args.paging.cursor);\n const limit = fromInputMaybe(args.paging.limit);\n if (cursor || limit) {\n paging = {\n cursor: cursor || \"\",\n limit: limit || 10,\n };\n }\n }\n\n let result: PagedResults<PHDocument>;\n try {\n result = await reactorClient.getIncomingRelationships(\n args.targetIdentifier,\n args.relationshipType,\n view,\n paging,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch incoming relationships: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toPhDocumentResultPage(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert incoming relationships to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function documentOutgoingRelationshipEdges(\n reactorClient: IReactorClient,\n args: {\n sourceIdentifier: string;\n relationshipType?: string | null;\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n paging?: {\n cursor?: string | null;\n limit?: number | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<DocumentRelationshipResultPage> {\n const view = toRelationshipViewFilter(args.view, subject);\n const paging = toRelationshipPagingOptions(args.paging);\n\n let result: PagedResults<DocumentRelationship>;\n try {\n result = await reactorClient.getOutgoingRelationshipEdges(\n args.sourceIdentifier,\n fromInputMaybe(args.relationshipType),\n view,\n paging,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch outgoing relationship edges: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toDocumentRelationshipResultPage(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert outgoing relationship edges to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function documentIncomingRelationshipEdges(\n reactorClient: IReactorClient,\n args: {\n targetIdentifier: string;\n relationshipType?: string | null;\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n paging?: {\n cursor?: string | null;\n limit?: number | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<DocumentRelationshipResultPage> {\n const view = toRelationshipViewFilter(args.view, subject);\n const paging = toRelationshipPagingOptions(args.paging);\n\n let result: PagedResults<DocumentRelationship>;\n try {\n result = await reactorClient.getIncomingRelationshipEdges(\n args.targetIdentifier,\n fromInputMaybe(args.relationshipType),\n view,\n paging,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch incoming relationship edges: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toDocumentRelationshipResultPage(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert incoming relationship edges to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nfunction toRelationshipViewFilter(\n input:\n | {\n branch?: string | null;\n scopes?: readonly string[] | null;\n }\n | null\n | undefined,\n subject?: AuthSubject,\n): ViewFilter | undefined {\n if (!input) {\n return subject ? { subject } : undefined;\n }\n\n return {\n subject,\n branch: fromInputMaybe(input.branch),\n scopes: toMutableArray(fromInputMaybe(input.scopes)),\n };\n}\n\nfunction toRelationshipPagingOptions(\n input:\n | {\n cursor?: string | null;\n limit?: number | null;\n }\n | null\n | undefined,\n): PagingOptions | undefined {\n if (!input) {\n return undefined;\n }\n\n const cursor = fromInputMaybe(input.cursor);\n const limit = fromInputMaybe(input.limit);\n if (!cursor && !limit) {\n return undefined;\n }\n\n return { cursor: cursor || \"\", limit: limit || 10 };\n}\n\nexport async function findDocuments(\n reactorClient: IReactorClient,\n args: {\n search: {\n type?: string | null;\n parentId?: string | null;\n };\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n paging?: {\n cursor?: string | null;\n limit?: number | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<PhDocumentResultPage> {\n let view: ViewFilter | undefined = subject ? { subject } : undefined;\n if (args.view) {\n view = {\n subject,\n branch: fromInputMaybe(args.view.branch),\n scopes: toMutableArray(fromInputMaybe(args.view.scopes)),\n };\n }\n\n let paging: PagingOptions | undefined;\n if (args.paging) {\n const cursor = fromInputMaybe(args.paging.cursor);\n const limit = fromInputMaybe(args.paging.limit);\n if (cursor || limit) {\n paging = {\n cursor: cursor || \"\",\n limit: limit || 10,\n };\n }\n }\n\n const search: SearchFilter = {\n type: fromInputMaybe(args.search.type),\n parentId: fromInputMaybe(args.search.parentId),\n };\n\n let result: PagedResults<PHDocument>;\n try {\n result = await reactorClient.find(search, view, paging);\n } catch (error) {\n throw new GraphQLError(\n `Failed to find documents: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toPhDocumentResultPage(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert documents to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\n/**\n * The answer for a job the caller may not see, shaped as the reactor answers\n * an unknown one so that the two cannot be told apart.\n */\nfunction unknownJob(jobId: string): JobInfo {\n const now = new Date().toISOString();\n return {\n id: jobId,\n documentId: \"\",\n status: JobStatus.FAILED,\n createdAtUtcIso: now,\n completedAtUtcIso: now,\n error: { name: \"Error\", message: \"Job not found\", stack: \"\" },\n consistencyToken: { version: 1, createdAtUtcIso: now, coordinates: [] },\n meta: { batchId: jobId, batchJobIds: [jobId] },\n };\n}\n\nexport async function jobStatus(\n reactorClient: IReactorClient,\n args: {\n jobId: string;\n },\n serves: (documentId: string) => Promise<boolean>,\n): Promise<GqlJobInfo> {\n let result: JobInfo;\n try {\n result = await reactorClient.getJobStatus(args.jobId);\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch job status: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n if (!(await serves(result.documentId))) {\n result = unknownJob(args.jobId);\n }\n\n try {\n return toGqlJobInfo(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert job status to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function documentOperations(\n reactorClient: IReactorClient,\n args: {\n filter: {\n documentId: string;\n branch?: string | null;\n scopes?: readonly string[] | null;\n actionTypes?: readonly string[] | null;\n sinceRevision?: number | null;\n timestampFrom?: string | null;\n timestampTo?: string | null;\n };\n paging?: {\n cursor?: string | null;\n limit?: number | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<ReactorOperationResultPage> {\n let view: ViewFilter | undefined = subject ? { subject } : undefined;\n const branch = fromInputMaybe(args.filter.branch);\n const scopes = toMutableArray(fromInputMaybe(args.filter.scopes));\n if (branch || scopes) {\n view = { subject, branch, scopes };\n }\n\n const actionTypes = toMutableArray(fromInputMaybe(args.filter.actionTypes));\n const sinceRevision = fromInputMaybe(args.filter.sinceRevision);\n const timestampFrom = fromInputMaybe(args.filter.timestampFrom);\n const timestampTo = fromInputMaybe(args.filter.timestampTo);\n\n let operationFilter: OperationFilter | undefined;\n if (\n (actionTypes && actionTypes.length > 0) ||\n sinceRevision !== undefined ||\n timestampFrom ||\n timestampTo\n ) {\n operationFilter = {\n actionTypes:\n actionTypes && actionTypes.length > 0 ? actionTypes : undefined,\n sinceRevision,\n timestampFrom: timestampFrom || undefined,\n timestampTo: timestampTo || undefined,\n };\n }\n\n let paging: PagingOptions | undefined;\n if (args.paging) {\n const cursor = fromInputMaybe(args.paging.cursor);\n const limit = fromInputMaybe(args.paging.limit);\n if (cursor || limit) {\n paging = {\n cursor: cursor || \"\",\n limit: limit || 100,\n };\n }\n }\n\n let result: PagedResults<Operation>;\n try {\n result = await reactorClient.getOperations(\n args.filter.documentId,\n view,\n operationFilter,\n paging,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to fetch document operations: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toOperationResultPage(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert operations to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\n/**\n * Predicts the admission verdict for each candidate operation, deciding against\n * the document policy through the reactor's own decision model.\n *\n * The subject is supplied by the subgraph from the authenticated request, never\n * by the caller: answering for an arbitrary subject would disclose what a policy\n * grants somebody else. It carries the caller's address and the app key their\n * token authenticated with, which is the same pair a signed action presents, so\n * a grant naming either matches here exactly as it would at admission.\n *\n * A reactor without authEnforcement raises the named error, which becomes an\n * \"unsupported\" code rather than a denial.\n */\nexport async function evaluateActions(\n reactorClient: IReactorClient,\n args: {\n documentIdentifier: string;\n branch?: string | null;\n candidates: ReadonlyArray<{\n scope: string;\n type: string;\n input?: unknown;\n }>;\n },\n subject?: AuthSubject,\n): Promise<GqlActionEvaluations> {\n const branch = fromInputMaybe(args.branch) ?? \"main\";\n const candidates: ActionCandidate[] = args.candidates.map((candidate) => ({\n scope: candidate.scope,\n type: candidate.type,\n input: fromInputMaybe(candidate.input),\n }));\n\n let result: ActionEvaluations;\n try {\n result = await reactorClient.evaluateActions(\n args.documentIdentifier,\n branch,\n candidates,\n subject,\n );\n } catch (error) {\n if (AuthEnforcementDisabledError.isError(error)) {\n throw new AuthEvaluationUnsupportedError();\n }\n throw new GraphQLError(\n `Failed to evaluate actions: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n return {\n evaluations: result.evaluations.map(toGqlActionEvaluation),\n allAllowed: result.allAllowed,\n anyAllowed: result.anyAllowed,\n allDenied: result.allDenied,\n anyDenied: result.anyDenied,\n };\n}\n\nexport async function createDocument(\n reactorClient: IReactorClient,\n args: {\n document: unknown;\n parentIdentifier?: string | null;\n },\n reactorDriveClient?: IDriveClient,\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n // Validate that document is a PHDocument\n if (!args.document || typeof args.document !== \"object\") {\n throw new GraphQLError(\"Invalid document: must be an object\");\n }\n\n const document = args.document as PHDocument;\n\n // Validate required fields\n if (!document.header || typeof document.header !== \"object\") {\n throw new GraphQLError(\"Invalid document: missing or invalid header\");\n }\n\n const parentIdentifier = fromInputMaybe(args.parentIdentifier);\n\n let result: PHDocument;\n try {\n if (parentIdentifier) {\n const parent = await reactorClient.get(\n parentIdentifier,\n subject && { subject },\n );\n if (isDriveContainerType(parent.header.documentType)) {\n const driveClient = pickDriveClient(\n reactorClient,\n parent.header.documentType,\n reactorDriveClient,\n );\n result = await driveClient.addFile(parentIdentifier, document);\n } else {\n result = await reactorClient.create(document, parentIdentifier);\n }\n } else {\n result = await reactorClient.create(document);\n }\n } catch (error) {\n throw new GraphQLError(\n `Failed to create document: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = await readAsCaller(reactorClient, result, subject);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert created document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function createEmptyDocument(\n reactorClient: IReactorClient,\n args: {\n documentType: string;\n parentIdentifier?: string | null;\n name?: string | null;\n },\n reactorDriveClient?: IDriveClient,\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const parentIdentifier = fromInputMaybe(args.parentIdentifier);\n const name = fromInputMaybe(args.name);\n\n let result: PHDocument;\n try {\n if (parentIdentifier) {\n const parent = await reactorClient.get(\n parentIdentifier,\n subject && { subject },\n );\n if (isDriveContainerType(parent.header.documentType)) {\n const module = await reactorClient.getDocumentModelModule(\n args.documentType,\n );\n const document = withSignaturePolicy(\n module.utils.createDocument(),\n await reactorClient.getCreateSignaturePolicy(),\n );\n if (name) {\n document.header.name = name;\n }\n const driveClient = pickDriveClient(\n reactorClient,\n parent.header.documentType,\n reactorDriveClient,\n );\n result = await driveClient.addFile(parentIdentifier, document);\n } else {\n result = await reactorClient.createEmpty(args.documentType, {\n parentIdentifier,\n });\n }\n } else {\n result = await reactorClient.createEmpty(args.documentType, {});\n }\n } catch (error) {\n throw new GraphQLError(\n `Failed to create empty document: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = await readAsCaller(reactorClient, result, subject);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert created document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function createDocumentWithInitialState(\n reactorClient: IReactorClient,\n args: {\n documentType: string;\n parentIdentifier?: string | null;\n name?: string | null;\n slug?: string | null;\n preferredEditor?: string | null;\n initialState: Record<string, Record<string, unknown>>;\n },\n reactorDriveClient?: IDriveClient,\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const parentIdentifier = fromInputMaybe(args.parentIdentifier);\n const name = fromInputMaybe(args.name);\n const slug = fromInputMaybe(args.slug);\n const preferredEditor = fromInputMaybe(args.preferredEditor);\n\n let module: DocumentModelModule;\n try {\n module = await reactorClient.getDocumentModelModule(args.documentType);\n } catch (error) {\n throw new GraphQLError(\n `Document model not found for type ${args.documentType}: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n const document = withSignaturePolicy(\n module.utils.createDocument(),\n await reactorClient.getCreateSignaturePolicy(),\n );\n\n // Only merge specification-defined scopes (e.g., global, local).\n // Protected scopes like \"auth\" and \"document\" are excluded.\n const allowedScopes = new Set(\n Object.keys(module.documentModel.global.specifications.at(-1)?.state ?? {}),\n );\n const state = document.state as Record<string, Record<string, unknown>>;\n for (const [scope, scopeState] of Object.entries(args.initialState)) {\n if (allowedScopes.has(scope) && scope in state) {\n state[scope] = { ...state[scope], ...scopeState };\n }\n }\n\n if (name) {\n document.header.name = name;\n }\n if (slug) {\n document.header.slug = slug;\n }\n if (preferredEditor) {\n document.header.meta = { ...document.header.meta, preferredEditor };\n }\n\n let result: PHDocument;\n if (parentIdentifier) {\n let parent: PHDocument;\n try {\n parent = await reactorClient.get(\n parentIdentifier,\n subject && { subject },\n );\n } catch (error) {\n throw new GraphQLError(\n `Parent document not found: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n if (isDriveContainerType(parent.header.documentType)) {\n const driveClient = pickDriveClient(\n reactorClient,\n parent.header.documentType,\n reactorDriveClient,\n );\n try {\n result = await driveClient.addFile(parentIdentifier, document);\n } catch (error) {\n throw new GraphQLError(\n `Failed to create document in drive: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n } else {\n try {\n result = await reactorClient.create(document, parentIdentifier);\n } catch (error) {\n throw new GraphQLError(\n `Failed to create document with parent: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n }\n } else {\n try {\n result = await reactorClient.create(document);\n } catch (error) {\n throw new GraphQLError(\n `Failed to create document: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n }\n\n result = await readAsCaller(reactorClient, result, subject);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert created document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\n/** The branch a mutation applies to when the caller names none. */\nconst DEFAULT_BRANCH = \"main\";\n\n/**\n * Applies actions to a document and waits for the result.\n *\n * The wire form of `IReactorClient.execute`, and named for it. Takes the actions\n * already coerced against `ActionInput`, so the only conversion left is the one\n * the schema cannot express: a signature travels as one string, and verification\n * reads it as the tuple it was.\n */\nexport async function execute(\n reactorClient: IReactorClient,\n args: {\n documentIdentifier: string;\n actions: readonly ActionInput[];\n branch?: string | null;\n },\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const actions = toSubmittableActions(args.actions);\n const branch = fromInputMaybe(args.branch) ?? DEFAULT_BRANCH;\n\n let result: PHDocument;\n try {\n result = await reactorClient.execute(\n args.documentIdentifier,\n branch,\n actions,\n undefined,\n subject,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to execute actions: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert executed document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\n/**\n * Submits actions to a document and returns the job that will apply them.\n *\n * Returns the job rather than only its id, matching\n * `IReactorClient.executeAsync`. A job handed back from a submission has no\n * result yet, which is why `JobInfo.result` is nullable.\n */\nexport async function executeAsync(\n reactorClient: IReactorClient,\n args: {\n documentIdentifier: string;\n actions: readonly ActionInput[];\n branch?: string | null;\n },\n): Promise<GqlJobInfo> {\n const actions = toSubmittableActions(args.actions);\n const branch = fromInputMaybe(args.branch) ?? DEFAULT_BRANCH;\n\n let job: JobInfo;\n try {\n job = await reactorClient.executeAsync(\n args.documentIdentifier,\n branch,\n actions,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to submit actions: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n return toGqlJobInfo(job);\n}\n\nexport async function mutateDocument(\n reactorClient: IReactorClient,\n args: {\n documentIdentifier: string;\n actions: readonly unknown[];\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n },\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n // Validate actions\n let validatedActions;\n try {\n validatedActions = validateActions(args.actions);\n } catch (error) {\n if (error instanceof GraphQLError) {\n throw error;\n }\n throw new GraphQLError(\n `Action validation failed: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // Extract branch from view filter (default to \"main\")\n const branch = args.view?.branch ?? \"main\";\n\n let result: PHDocument;\n try {\n result = await reactorClient.execute(\n args.documentIdentifier,\n branch,\n validatedActions,\n undefined,\n subject,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to mutate document: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert mutated document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function mutateDocumentAsync(\n reactorClient: IReactorClient,\n args: {\n documentIdentifier: string;\n actions: readonly unknown[];\n view?: {\n branch?: string | null;\n scopes?: readonly string[] | null;\n } | null;\n },\n): Promise<string> {\n // Validate actions\n let validatedActions;\n try {\n validatedActions = validateActions(args.actions);\n } catch (error) {\n if (error instanceof GraphQLError) {\n throw error;\n }\n throw new GraphQLError(\n `Action validation failed: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // Extract branch from view filter (default to \"main\")\n const branch = args.view?.branch ?? \"main\";\n\n let result: JobInfo;\n try {\n result = await reactorClient.executeAsync(\n args.documentIdentifier,\n branch,\n validatedActions,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to submit document mutation: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n return result.id;\n}\n\nexport async function renameDocument(\n reactorClient: IReactorClient,\n args: {\n documentIdentifier: string;\n name: string;\n branch?: string | null;\n },\n signal?: AbortSignal,\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const branch = fromInputMaybe(args.branch);\n\n let result: PHDocument;\n try {\n result = await reactorClient.rename(\n args.documentIdentifier,\n args.name,\n branch,\n signal,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to rename document: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = await readAsCaller(reactorClient, result, subject, branch);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert renamed document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function setPreferredEditor(\n reactorClient: IReactorClient,\n args: {\n documentIdentifier: string;\n preferredEditor?: string | null;\n branch?: string | null;\n },\n signal?: AbortSignal,\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const branch = fromInputMaybe(args.branch);\n const preferredEditor = fromInputMaybe(args.preferredEditor) ?? null;\n\n let result: PHDocument;\n try {\n result = await reactorClient.setPreferredEditor(\n args.documentIdentifier,\n preferredEditor,\n branch,\n signal,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to set preferred editor: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = await readAsCaller(reactorClient, result, subject, branch);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert updated document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function addRelationship(\n reactorClient: IReactorClient,\n args: {\n sourceIdentifier: string;\n targetIdentifier: string;\n relationshipType: string;\n metadata?: Record<string, unknown> | null;\n branch?: string | null;\n },\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const branch = fromInputMaybe(args.branch);\n const metadata = fromInputMaybe(args.metadata);\n\n let result: PHDocument;\n try {\n result = await reactorClient.addRelationship(\n args.sourceIdentifier,\n args.targetIdentifier,\n args.relationshipType,\n metadata,\n branch,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to add relationship: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = await readAsCaller(reactorClient, result, subject, branch);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function updateRelationship(\n reactorClient: IReactorClient,\n args: {\n sourceIdentifier: string;\n targetIdentifier: string;\n relationshipType: string;\n metadata?: Record<string, unknown> | null;\n branch?: string | null;\n },\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const branch = fromInputMaybe(args.branch);\n // The action's metadata is required and nullable: omitting it clears the edge.\n const metadata = fromInputMaybe(args.metadata) ?? null;\n\n let result: PHDocument;\n try {\n result = await reactorClient.updateRelationship(\n args.sourceIdentifier,\n args.targetIdentifier,\n args.relationshipType,\n metadata,\n branch,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to update relationship: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = await readAsCaller(reactorClient, result, subject, branch);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function removeRelationship(\n reactorClient: IReactorClient,\n args: {\n sourceIdentifier: string;\n targetIdentifier: string;\n relationshipType: string;\n branch?: string | null;\n },\n subject?: AuthSubject,\n): Promise<ReturnType<typeof toGqlPhDocument>> {\n const branch = fromInputMaybe(args.branch);\n\n let result: PHDocument;\n try {\n result = await reactorClient.removeRelationship(\n args.sourceIdentifier,\n args.targetIdentifier,\n args.relationshipType,\n branch,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to remove relationship: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = await readAsCaller(reactorClient, result, subject, branch);\n\n try {\n return toGqlPhDocument(result);\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert document to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function moveRelationship(\n reactorClient: IReactorClient,\n args: {\n sourceParentIdentifier: string;\n targetParentIdentifier: string;\n targetIdentifier: string;\n relationshipType: string;\n branch?: string | null;\n },\n subject?: AuthSubject,\n): Promise<{\n source: ReturnType<typeof toGqlPhDocument>;\n target: ReturnType<typeof toGqlPhDocument>;\n}> {\n const branch = fromInputMaybe(args.branch);\n\n let result: { source: PHDocument; target: PHDocument };\n try {\n result = await reactorClient.moveRelationship(\n args.sourceParentIdentifier,\n args.targetParentIdentifier,\n args.targetIdentifier,\n args.relationshipType,\n branch,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to move relationship: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n result = {\n source: await readAsCaller(reactorClient, result.source, subject, branch),\n target: await readAsCaller(reactorClient, result.target, subject, branch),\n };\n\n try {\n return {\n source: toGqlPhDocument(result.source),\n target: toGqlPhDocument(result.target),\n };\n } catch (error) {\n throw new GraphQLError(\n `Failed to convert documents to GraphQL: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function deleteDocument(\n reactorClient: IReactorClient,\n args: {\n identifier: string;\n propagate?: GqlPropagationMode | null;\n },\n reactorDriveClient?: IDriveClient,\n): Promise<boolean> {\n const propagate = toReactorPropagationMode(args.propagate);\n\n try {\n const incoming = await reactorClient.getIncomingRelationships(\n args.identifier,\n \"child\",\n );\n const driveParent = incoming.results.find((p) =>\n isDriveContainerType(p.header.documentType),\n );\n if (driveParent) {\n const driveClient = pickDriveClient(\n reactorClient,\n driveParent.header.documentType,\n reactorDriveClient,\n );\n await driveClient.removeNode(driveParent.header.id, args.identifier);\n } else {\n await reactorClient.deleteDocument(args.identifier, propagate);\n }\n return true;\n } catch (error) {\n throw new GraphQLError(\n `Failed to delete document: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\nexport async function deleteDocuments(\n reactorClient: IReactorClient,\n args: {\n identifiers: readonly string[];\n propagate?: GqlPropagationMode | null;\n },\n): Promise<boolean> {\n const propagate = toReactorPropagationMode(args.propagate);\n const identifiers = [...args.identifiers];\n\n try {\n await reactorClient.deleteDocuments(identifiers, propagate);\n return true;\n } catch (error) {\n throw new GraphQLError(\n `Failed to delete documents: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n}\n\n/**\n * Registers a sync channel, or reports the state of one already registered.\n *\n * `boundAddress` claims a channel at creation for the subject that created it.\n * An anonymously created channel is left unbound, which is not a permission but\n * an unanswered question: the first authenticated subject to use it adopts it.\n */\nexport async function touchChannel(\n syncManager: ISyncManager,\n args: {\n input: {\n id: string;\n name: string;\n collectionId: string;\n filter: {\n documentId: readonly string[];\n scope: readonly string[];\n branch: string;\n };\n sinceTimestampUtcMs: string;\n };\n },\n boundAddress?: string,\n): Promise<{ success: boolean; ackOrdinal: number }> {\n try {\n const remote = syncManager.getById(args.input.id);\n\n return {\n success: true,\n ackOrdinal: remote.channel.inbox.ackOrdinal,\n };\n } catch {\n // getById will throw if the remote does not exist\n }\n\n const filter: RemoteFilter = {\n documentId: [...args.input.filter.documentId],\n scope: [...args.input.filter.scope],\n branch: args.input.filter.branch,\n };\n\n const options = {\n sinceTimestampUtcMs: args.input.sinceTimestampUtcMs,\n boundAddress,\n };\n\n try {\n await syncManager.add(\n args.input.name,\n DriveCollectionId.fromKey(args.input.collectionId),\n {\n type: \"polling\",\n parameters: {},\n },\n filter,\n options,\n args.input.id,\n );\n } catch (error) {\n throw new GraphQLError(\n `Failed to create channel: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n return { success: true, ackOrdinal: 0 };\n}\n\n/**\n * The sync operations in `syncOps` this subject may not be served.\n *\n * A sync operation is one document, one branch and (from the outbox) one scope,\n * so the answer is per entry rather than per operation: an entry is withheld\n * whole or served whole, which is what keeps a scope's operation sequence\n * unbroken for whoever does receive it. A dead letter can name several scopes,\n * and is withheld only when the policy serves none of them -- the metadata\n * scopes are readable by every holder, so in practice a dead letter naming one\n * is always served.\n *\n * The policy is read once per document and branch, and the memo lives no longer\n * than this call: a poll must not answer from a policy that changed between\n * polls, since the widening case is exactly the one holding exists to serve.\n *\n * A read that fails for any reason other than the document being absent is\n * allowed to propagate. The poll then fails, the puller retries, and nothing is\n * served in the meantime -- which is the safe direction, and a visible one.\n */\nexport async function collectHeldSyncOperations(\n syncOps: ReadonlyArray<SyncOperation>,\n gate: SyncScopeGate,\n subject: AuthSubject,\n signal?: AbortSignal,\n): Promise<Set<string>> {\n const held = new Set<string>();\n const predicates = new Map<string, Promise<(scope: string) => boolean>>();\n\n for (const syncOp of syncOps) {\n const key = `${syncOp.documentId}\\u0000${syncOp.branch}`;\n let predicate = predicates.get(key);\n if (!predicate) {\n predicate = gate.scopePredicateById(\n syncOp.documentId,\n subject,\n syncOp.branch,\n signal,\n );\n predicates.set(key, predicate);\n }\n\n const readable = await predicate;\n if (!syncOp.scopes.some((scope) => readable(scope))) {\n held.add(syncOp.id);\n }\n }\n\n return held;\n}\n\n/**\n * Polls the switchboard for new sync envelopes and acknowledges previously\n * received operations.\n *\n * `forbiddenIds` and `heldOpIds` are two different refusals. A forbidden\n * document is consumed: its delivery counters are advanced as though it had\n * been sent, so it is never reconsidered. A held sync operation is withheld:\n * nothing about it is touched, so a policy that later widens serves it whole on\n * a subsequent poll. Which one applies is the caller's decision, and the two\n * are intersected, so a document refused either way is not served.\n *\n * Ordinal frames of reference:\n * - `outboxAck` / `outboxLatest`: switchboard's ordinals (used to trim/filter\n * the switchboard's outbox)\n * - `ackOrdinal` in the response: the pushing client's ordinals (highest\n * client ordinal the switchboard has successfully applied, so the client\n * can trim its own outbox)\n */\nexport function pollSyncEnvelopes(\n syncManager: ISyncManager,\n args: {\n channelId: string;\n outboxAck: number;\n outboxLatest: number;\n },\n forbiddenIds: ReadonlySet<string> = new Set(),\n heldOpIds: ReadonlySet<string> = new Set(),\n gatedOpIds?: ReadonlySet<string>,\n): {\n envelopes: any[];\n ackOrdinal: number;\n deadLetters: Array<{\n documentId: string;\n error: string;\n errorType: string;\n jobId: string;\n branch: string;\n scopes: string[];\n operationCount: number;\n }>;\n hasMore: boolean;\n} {\n // The gate ran against a snapshot taken before its first await, so an entry\n // the outbox gained while it was deciding carries no verdict. Serving one\n // would hand over a scope nobody authorized, so an entry the gate never saw\n // is held exactly like one it refused -- withheld, not consumed, which leaves\n // it in the outbox for the next poll to evaluate properly.\n const isHeld = (syncOp: SyncOperation): boolean =>\n heldOpIds.has(syncOp.id) ||\n (gatedOpIds !== undefined && !gatedOpIds.has(syncOp.id));\n\n let remote;\n try {\n remote = syncManager.getById(args.channelId);\n } catch (error) {\n throw new GraphQLError(\n `Channel not found: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // The subgraph's drive and binding checks run before this call, so reaching\n // here is an authorized poll: the only evidence the switchboard has that this\n // channel still has a holder.\n remote.channel.notePoll();\n\n // Dead-letter items can originate from failed inbox jobs whose documentId is\n // outside this channel's collection, so they are filtered by the caller's read\n // access independently of the outbox (see the poll resolver in subgraph.ts).\n const deadLetters = remote.channel.deadLetter.items\n .filter((syncOp) => !forbiddenIds.has(syncOp.documentId) && !isHeld(syncOp))\n .map((syncOp) => ({\n documentId: syncOp.documentId,\n error: syncOp.error?.message ?? \"Unknown error\",\n // Sent so a peer mirrors this replica's quarantine decision rather than\n // freezing a document it is deliberately still syncing.\n errorType: syncOperationErrorType(syncOp.error),\n jobId: syncOp.jobId,\n branch: syncOp.branch,\n scopes: syncOp.scopes,\n operationCount: syncOp.operations.length,\n }));\n\n // Trim acked outbox items, but only those we have fully emitted to this\n // client. Without the emittedCount guard, a syncOp queued behind a page cap\n // (never sent) would be dropped when ackOrdinal sweeps past its ordinals,\n // because ackOrdinal can be advanced by OTHER syncOps the client did\n // receive — same root-cause class as the resolver's per-op filter bug.\n if (args.outboxAck > 0) {\n const ackOrdinal = args.outboxAck;\n const outbox = remote.channel.outbox;\n const toRemove: SyncOperation[] = [];\n for (const syncOp of outbox.items) {\n const fullyEmitted =\n (syncOp.emittedCount ?? 0) >= syncOp.operations.length;\n if (!fullyEmitted) continue;\n let maxOrdinal = 0;\n for (const op of syncOp.operations) {\n if (op.context.ordinal > maxOrdinal) maxOrdinal = op.context.ordinal;\n }\n if (maxOrdinal <= ackOrdinal) {\n toRemove.push(syncOp);\n }\n }\n if (toRemove.length > 0) {\n for (const syncOp of toRemove) {\n syncOp.executed();\n }\n outbox.remove(...toRemove);\n }\n }\n\n const operations = remote.channel.outbox.items;\n\n // Drain forbidden operations: mark them fully delivered so the page loop's\n // `remaining.length === 0` guard skips them (never emitted to this caller) and\n // the ack trim above evicts them on a later poll. The caller proved they may\n // not read these documents, so advancing the cursor past them is correct and\n // avoids re-evaluating them every poll.\n if (forbiddenIds.size > 0) {\n for (const syncOp of operations) {\n if (forbiddenIds.has(syncOp.documentId)) {\n syncOp.deliveredCount = syncOp.operations.length;\n syncOp.emittedCount = syncOp.operations.length;\n }\n }\n }\n\n if (operations.length === 0) {\n return {\n envelopes: [],\n ackOrdinal: remote.channel.inbox.ackOrdinal,\n deadLetters,\n hasMore: false,\n };\n }\n\n // Dependencies point backward in ordinal order, so sorting by first op\n // ordinal preserves dependency ordering across the page.\n const sorted = [...operations].sort((a, b) => {\n const aOrdinal = a.operations[0]?.context.ordinal ?? 0;\n const bOrdinal = b.operations[0]?.context.ordinal ?? 0;\n return aOrdinal - bOrdinal;\n });\n\n const envelopes: SyncEnvelopeArg[] = [];\n let pageOps = 0;\n let hasMore = false;\n let maxOrdinal = args.outboxLatest;\n\n outer: for (const syncOp of sorted) {\n if (pageOps >= MAX_OPERATIONS_PER_PAGE) {\n hasMore = true;\n break;\n }\n\n // Before the delivery cursor is read or written, because holding must leave\n // no trace: the counters are what a later ack sweep consults to decide the\n // entry was delivered and may be evicted. A hold sets no hasMore either --\n // there is no later page that would serve it, so claiming one would spin the\n // puller.\n if (isHeld(syncOp)) continue;\n\n // Advance the per-syncOp delivery cursor past leading ops the client has\n // both received (outboxLatest) and we have previously emitted\n // (emittedCount). Gating on emittedCount prevents skipping ops that were\n // never sent because an earlier syncOp filled the page cap — a syncOp\n // queued behind that cap has emittedCount = 0 and stays un-advanced even\n // when outboxLatest sweeps past its ordinals. Gating on outboxLatest\n // (rather than emittedCount alone) keeps response-loss recovery: emitted\n // but unconfirmed ops re-emit on the next poll.\n syncOp.deliveredCount ??= 0;\n syncOp.emittedCount ??= 0;\n while (\n syncOp.deliveredCount < syncOp.emittedCount &&\n syncOp.operations[syncOp.deliveredCount].context.ordinal <=\n args.outboxLatest\n ) {\n syncOp.deliveredCount += 1;\n }\n\n const remaining = syncOp.operations.slice(syncOp.deliveredCount);\n if (remaining.length === 0) continue;\n\n let prevPartKey: string | undefined;\n let partIdx = 0;\n let i = 0;\n while (i < remaining.length) {\n if (pageOps >= MAX_OPERATIONS_PER_PAGE) {\n hasMore = true;\n break outer;\n }\n\n const remainingPage = MAX_OPERATIONS_PER_PAGE - pageOps;\n // Always emit at least one op so an oversized single op makes progress.\n const chunkSize = Math.max(\n 1,\n Math.min(\n MAX_OPERATIONS_PER_ENVELOPE,\n remainingPage,\n remaining.length - i,\n ),\n );\n const slice = remaining.slice(i, i + chunkSize);\n\n const isOnly =\n remaining.length <= MAX_OPERATIONS_PER_ENVELOPE &&\n remaining.length <= remainingPage;\n const baseKey = syncOp.jobId || undefined;\n const partKey = isOnly\n ? baseKey\n : baseKey\n ? `${baseKey}__p${partIdx}`\n : undefined;\n const partDeps =\n partIdx === 0\n ? syncOp.jobDependencies.filter(Boolean)\n : prevPartKey\n ? [prevPartKey]\n : [];\n\n for (const op of slice) {\n if (op.context.ordinal > maxOrdinal) maxOrdinal = op.context.ordinal;\n }\n\n envelopes.push({\n type: \"OPERATIONS\",\n channelMeta: { id: args.channelId },\n operations: slice.map((op) => ({\n operation: serializeOperationForGraphQL(op.operation),\n context: op.context,\n })),\n cursor: {\n remoteName: remote.meta.name,\n cursorOrdinal: 0,\n lastSyncedAtUtcMs: Date.now().toString(),\n },\n key: partKey,\n dependsOn: partDeps.length > 0 ? partDeps : undefined,\n });\n\n pageOps += slice.length;\n i += slice.length;\n prevPartKey = partKey;\n partIdx++;\n\n // Record how far through this syncOp we have emitted. The cursor advance\n // above only moves past ops counted here, so an unsent syncOp (e.g. one\n // that never reached emission because of the page cap) cannot have its\n // delivery cursor advanced by a future poll's outboxLatest.\n const emittedThrough = syncOp.deliveredCount + i;\n if (emittedThrough > syncOp.emittedCount) {\n syncOp.emittedCount = emittedThrough;\n }\n\n if (i < remaining.length && pageOps >= MAX_OPERATIONS_PER_PAGE) {\n hasMore = true;\n break outer;\n }\n }\n }\n\n for (const envelope of envelopes) {\n if (envelope.cursor) envelope.cursor.cursorOrdinal = maxOrdinal;\n }\n\n return {\n envelopes,\n ackOrdinal: remote.channel.inbox.ackOrdinal,\n deadLetters,\n hasMore,\n };\n}\n\ntype SyncEnvelopeArg = {\n type: string;\n channelMeta: { id: string };\n operations?: Array<{\n operation: any;\n context: {\n documentId: string;\n documentType: string;\n scope: string;\n branch: string;\n ordinal: number;\n };\n }> | null;\n cursor?: {\n remoteName: string;\n cursorOrdinal: number;\n lastSyncedAtUtcMs?: string | null;\n } | null;\n key?: string;\n dependsOn?: string[];\n};\n\n/**\n * Receives sync envelopes pushed by a client and adds them to the\n * appropriate channel inboxes.\n *\n * The `ordinal` in each operation's context is the client's local ordinal.\n * It must be preserved because the inbox mailbox tracks applied ordinals\n * and returns the highest one as `ackOrdinal` in pollSyncEnvelopes.\n */\nexport function pushSyncEnvelopes(\n syncManager: ISyncManager,\n args: {\n envelopes: SyncEnvelopeArg[];\n },\n): Promise<boolean> {\n type RemoteRef = ReturnType<ISyncManager[\"getById\"]>;\n const remoteSyncOps = new Map<RemoteRef, SyncOperation[]>();\n\n for (const envelope of args.envelopes) {\n let remote: RemoteRef;\n try {\n remote = syncManager.getById(envelope.channelMeta.id);\n } catch (error) {\n throw new GraphQLError(\n `Channel not found: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n if (!envelope.operations || envelope.operations.length === 0) {\n continue;\n }\n\n // A Manual-poll holder never polls on a schedule, so a push is the only\n // liveness it ever reports. It is stamped below the empty-envelope exit,\n // and after the caller's per-operation checks upstream: an envelope\n // carrying nothing is authorized by nothing, so it proves nothing.\n remote.channel.notePoll();\n\n const syncOps = envelopesToSyncOperations(\n envelope as Parameters<typeof envelopesToSyncOperations>[0],\n remote.meta.name,\n );\n\n if (!remoteSyncOps.has(remote)) {\n remoteSyncOps.set(remote, []);\n }\n remoteSyncOps.get(remote)!.push(...syncOps);\n }\n\n for (const [remote, syncOps] of remoteSyncOps) {\n const consolidated = consolidateSyncOperations(syncOps);\n\n const validKeys = new Set(\n consolidated.map((op) => op.jobId).filter(Boolean),\n );\n for (const syncOp of consolidated) {\n syncOp.jobDependencies = syncOp.jobDependencies.filter((dep) =>\n validKeys.has(dep),\n );\n }\n\n remote.channel.inbox.add(...consolidated);\n }\n\n return Promise.resolve(true);\n}\n","import { camelCase, kebabCase } from \"change-case\";\nimport {\n setName,\n type DocumentModelModule,\n} from \"@powerhousedao/shared/document-model\";\nimport { GraphQLError, Kind, parse } from \"graphql\";\nimport {\n generateDocumentModelSchema,\n getDocumentModelSchemaName,\n} from \"../utils/create-schema.js\";\nimport type { CanonicalDocumentId } from \"../services/authorization.service.js\";\nimport { BaseSubgraph } from \"./base-subgraph.js\";\nimport { toGqlPhDocument } from \"./reactor/adapters.js\";\nimport type {\n PhDocument,\n PhDocumentResultPage,\n} from \"./reactor/gen/graphql.js\";\nimport {\n createDocumentWithInitialState as createDocumentWithInitialStateResolver,\n createEmptyDocument as createEmptyDocumentResolver,\n documentIncomingRelationships as documentIncomingRelationshipsResolver,\n documentOutgoingRelationships as documentOutgoingRelationshipsResolver,\n document as documentResolver,\n findDocuments as findDocumentsResolver,\n} from \"./reactor/resolvers.js\";\nimport type { Context, SubgraphArgs } from \"./types.js\";\n\n/** A resolver function that lives inside a document-model subgraph. */\n\nexport type DocumentModelResolverFn = (...args: any[]) => unknown;\n\n/**\n * A resolver map for a single GraphQL type in a document-model subgraph.\n * Each key is a field name (or `__resolveType` for unions) and each value\n * is a resolver function.\n */\nexport type DocumentModelResolverMap = Record<string, DocumentModelResolverFn>;\n\n/** View filter shared across query resolvers. */\ntype ViewArg = { branch?: string; scopes?: string[] };\n\n/** Paging argument shared across query resolvers. */\ntype PagingArg = { limit?: number; offset?: number; cursor?: string };\n\n/**\n * Known query resolvers generated for every document model.\n * `TDocument` is the GQL representation of the document (defaults to `PhDocument`).\n */\nexport interface DocumentModelQueryResolvers<\n TDocument extends PhDocument = PhDocument,\n> {\n document: (\n parent: unknown,\n args: { identifier: string; view?: ViewArg },\n ctx: Context,\n ) => Promise<{ document: TDocument; childIds: string[] }>;\n documents: (\n parent: unknown,\n args: { paging?: PagingArg },\n ctx: Context,\n ) => Promise<{ items: TDocument[] }>;\n findDocuments: (\n parent: unknown,\n args: {\n search?: { parentId?: string; identifiers?: string[] } | null;\n view?: ViewArg;\n paging?: PagingArg;\n },\n ctx: Context,\n ) => Promise<PhDocumentResultPage>;\n documentOutgoingRelationships: (\n parent: unknown,\n args: {\n sourceIdentifier: string;\n relationshipType: string;\n view?: ViewArg;\n paging?: PagingArg;\n },\n ctx: Context,\n ) => Promise<PhDocumentResultPage>;\n documentIncomingRelationships: (\n parent: unknown,\n args: {\n targetIdentifier: string;\n relationshipType: string;\n view?: ViewArg;\n paging?: PagingArg;\n },\n ctx: Context,\n ) => Promise<PhDocumentResultPage>;\n}\n\n/**\n * Known mutation resolvers generated for every document model.\n * `TDocument` is the GQL representation of the document (defaults to `PhDocument`).\n * Operations specific to each model are captured by the index signature.\n */\nexport interface DocumentModelMutationResolvers<\n TDocument extends PhDocument = PhDocument,\n> {\n createDocument: (\n parent: unknown,\n args: {\n name: string;\n parentIdentifier?: string;\n slug?: string;\n preferredEditor?: string;\n initialState?: Record<string, Record<string, unknown>>;\n },\n ctx: Context,\n ) => Promise<TDocument>;\n createEmptyDocument: (\n parent: unknown,\n args: { parentIdentifier?: string },\n ctx: Context,\n ) => Promise<TDocument>;\n /** Dynamic operation resolvers (sync and async variants). */\n [operationName: string]: DocumentModelResolverFn;\n}\n\n/** The resolvers that a `DocumentModelSubgraph` exposes. */\nexport interface DocumentModelSubgraphResolvers<\n TDocument extends PhDocument = PhDocument,\n> {\n Query: DocumentModelResolverMap;\n Mutation: DocumentModelResolverMap;\n [namespaceKey: string]:\n | DocumentModelResolverMap\n | DocumentModelQueryResolvers<TDocument>\n | DocumentModelMutationResolvers<TDocument>;\n}\n\n/**\n * New document model subgraph that uses reactorClient instead of legacy reactor.\n * This class auto-generates GraphQL queries and mutations for a document model.\n */\nexport class DocumentModelSubgraph extends BaseSubgraph {\n declare resolvers: DocumentModelSubgraphResolvers;\n private documentModel: DocumentModelModule;\n\n constructor(documentModel: DocumentModelModule, args: SubgraphArgs) {\n super(args);\n this.documentModel = documentModel;\n this.name = kebabCase(documentModel.documentModel.global.name);\n this.typeDefs = generateDocumentModelSchema(\n this.documentModel.documentModel.global,\n { useNewApi: true },\n );\n this.resolvers = this.generateResolvers();\n }\n\n /** Returns the typed query resolvers for this document model. */\n get queryResolvers(): DocumentModelQueryResolvers {\n const documentName = getDocumentModelSchemaName(\n this.documentModel.documentModel.global,\n );\n return this.resolvers[\n `${documentName}Queries`\n ] as DocumentModelQueryResolvers;\n }\n\n /** Returns the typed mutation resolvers for this document model. */\n get mutationResolvers(): DocumentModelMutationResolvers {\n const documentName = getDocumentModelSchemaName(\n this.documentModel.documentModel.global,\n );\n return this.resolvers[\n `${documentName}Mutations`\n ] as DocumentModelMutationResolvers;\n }\n\n /** Drops the items the host's own ACL refuses the caller. */\n async #readableItems(\n page: PhDocumentResultPage,\n ctx: Context,\n ): Promise<PhDocumentResultPage> {\n if (this.authorizationService.isSupremeAdmin(ctx.user?.address)) {\n return page;\n }\n const items: PhDocument[] = [];\n for (const item of page.items) {\n if (await this.canReadDocument(item.id as CanonicalDocumentId, ctx)) {\n items.push(item);\n }\n }\n return { ...page, items };\n }\n\n /**\n * Generate __resolveType functions for union types found in the document model schema.\n * Parses the state schema to find union definitions and their member types,\n * then uses unique field presence to discriminate between member types at runtime.\n */\n private generateUnionResolvers(): Record<string, DocumentModelResolverMap> {\n const documentName = getDocumentModelSchemaName(\n this.documentModel.documentModel.global,\n );\n const specification =\n this.documentModel.documentModel.global.specifications.at(-1);\n if (!specification) return {};\n\n const globalSchema = specification.state.global.schema ?? \"\";\n const localSchema = specification.state.local.schema ?? \"\";\n const fullSchema = `${globalSchema}\\n${localSchema}`;\n\n if (!fullSchema.trim()) return {};\n\n let ast;\n try {\n ast = parse(fullSchema);\n } catch {\n return {};\n }\n\n // Build map: object type name -> field names\n const objectFieldsMap = new Map<string, string[]>();\n for (const def of ast.definitions) {\n if (def.kind === Kind.OBJECT_TYPE_DEFINITION) {\n objectFieldsMap.set(\n def.name.value,\n def.fields?.map((f) => f.name.value) ?? [],\n );\n }\n }\n\n const resolvers: Record<string, DocumentModelResolverMap> = {};\n\n for (const def of ast.definitions) {\n if (def.kind !== Kind.UNION_TYPE_DEFINITION) continue;\n\n const unionName = def.name.value;\n const memberTypes = def.types?.map((t) => t.name.value) ?? [];\n if (memberTypes.length === 0) continue;\n\n // Compute unique fields per member type\n const uniqueFields: Record<string, string[]> = {};\n for (const memberType of memberTypes) {\n const ownFields = objectFieldsMap.get(memberType) ?? [];\n const otherFields = new Set(\n memberTypes\n .filter((t) => t !== memberType)\n .flatMap((t) => objectFieldsMap.get(t) ?? []),\n );\n uniqueFields[memberType] = ownFields.filter((f) => !otherFields.has(f));\n }\n\n const prefixedUnionName = `${documentName}_${unionName}`;\n\n resolvers[prefixedUnionName] = {\n __resolveType: (obj: Record<string, unknown>) => {\n for (const memberType of memberTypes) {\n const fields = uniqueFields[memberType] ?? [];\n if (fields.length > 0 && fields.some((f) => f in obj)) {\n return `${documentName}_${memberType}`;\n }\n }\n return `${documentName}_${memberTypes[0]}`;\n },\n };\n }\n\n return resolvers;\n }\n\n /**\n * Generate resolvers for this document model using reactorClient\n * Uses flat queries (not nested) consistent with ReactorSubgraph patterns\n */\n private generateResolvers(): DocumentModelSubgraphResolvers {\n const documentType = this.documentModel.documentModel.global.id;\n const documentName = getDocumentModelSchemaName(\n this.documentModel.documentModel.global,\n );\n const operations =\n this.documentModel.documentModel.global.specifications\n .at(-1)\n ?.modules.flatMap((module) =>\n module.operations.filter((op) => op.name),\n ) ?? [];\n\n return {\n ...this.generateUnionResolvers(),\n Query: {\n // Namespace resolver: returns empty object so nested field resolvers can run\n [documentName]: () => ({}),\n },\n [`${documentName}Queries`]: {\n // Get a specific document by identifier\n document: async (\n _: unknown,\n args: {\n identifier: string;\n view?: { branch?: string; scopes?: string[] };\n },\n ctx: Context,\n ) => {\n const { identifier, view } = args;\n\n if (!identifier) {\n throw new GraphQLError(\"Document identifier is required\");\n }\n\n const result = await documentResolver(\n this.reactorClient,\n { identifier, view },\n this.viewSubject(ctx),\n );\n\n if (result.document.documentType !== documentType) {\n throw new GraphQLError(\n `Document with id ${identifier} is not of type ${documentType}`,\n );\n }\n\n await this.assertCanReadCanonical(\n result.document.id as CanonicalDocumentId,\n ctx,\n );\n\n return result;\n },\n // Flat query: Get all documents of this type (paged)\n documents: async (\n _: unknown,\n args: {\n paging?: { limit?: number; offset?: number; cursor?: string };\n },\n ctx: Context,\n ) => {\n const { paging } = args;\n\n const result = await findDocumentsResolver(\n this.reactorClient,\n { search: { type: documentType }, paging },\n this.viewSubject(ctx),\n );\n\n return this.#readableItems(result, ctx);\n },\n // Flat query: Find documents by search criteria (type is built-in)\n // Uses shared findDocumentsResolver from reactor/resolvers.ts\n findDocuments: async (\n _: unknown,\n args: {\n search?: { parentId?: string; identifiers?: string[] } | null;\n view?: { branch?: string; scopes?: string[] };\n paging?: { limit?: number; offset?: number; cursor?: string };\n },\n ctx: Context,\n ) => {\n const { search, view, paging } = args;\n\n const result = await findDocumentsResolver(\n this.reactorClient,\n {\n search: { type: documentType, parentId: search?.parentId },\n view,\n paging,\n },\n this.viewSubject(ctx),\n );\n\n return this.#readableItems(result, ctx);\n },\n\n documentOutgoingRelationships: async (\n _: unknown,\n args: {\n sourceIdentifier: string;\n relationshipType: string;\n view?: { branch?: string; scopes?: string[] };\n paging?: { limit?: number; offset?: number; cursor?: string };\n },\n ctx: Context,\n ) => {\n const { relationshipType, view, paging } = args;\n\n const handle = await this.assertCanRead(args.sourceIdentifier, ctx);\n\n const result = await documentOutgoingRelationshipsResolver(\n this.reactorClient,\n {\n sourceIdentifier: handle.fetchIdentifier,\n relationshipType,\n view,\n paging,\n },\n this.viewSubject(ctx),\n );\n\n const readable = await this.#readableItems(result, ctx);\n const filteredItems = readable.items.filter(\n (item: PhDocument) => item.documentType === documentType,\n );\n\n return { ...readable, items: filteredItems };\n },\n\n documentIncomingRelationships: async (\n _: unknown,\n args: {\n targetIdentifier: string;\n relationshipType: string;\n view?: { branch?: string; scopes?: string[] };\n paging?: { limit?: number; offset?: number; cursor?: string };\n },\n ctx: Context,\n ) => {\n const { relationshipType, view, paging } = args;\n\n const handle = await this.assertCanRead(args.targetIdentifier, ctx);\n\n const result = await documentIncomingRelationshipsResolver(\n this.reactorClient,\n {\n targetIdentifier: handle.fetchIdentifier,\n relationshipType,\n view,\n paging,\n },\n this.viewSubject(ctx),\n );\n\n return this.#readableItems(result, ctx);\n },\n },\n Mutation: {\n // Namespace resolver: returns empty object so nested field resolvers can run\n [documentName]: () => ({}),\n },\n [`${documentName}Mutations`]: {\n createDocument: async (\n _: unknown,\n args: {\n name: string;\n parentIdentifier?: string;\n slug?: string;\n preferredEditor?: string;\n initialState?: Record<string, Record<string, unknown>>;\n },\n ctx: Context,\n ) => {\n const { name, slug, preferredEditor, initialState } = args;\n\n let parentIdentifier = args.parentIdentifier;\n if (parentIdentifier) {\n const handle = await this.assertCanWrite(parentIdentifier, ctx);\n parentIdentifier = handle.fetchIdentifier;\n } else {\n this.assertCanCreate(ctx);\n }\n\n let createdDoc;\n if (initialState || preferredEditor) {\n createdDoc = await createDocumentWithInitialStateResolver(\n this.reactorClient,\n {\n documentType,\n parentIdentifier,\n name,\n slug,\n preferredEditor,\n initialState: initialState ?? {},\n },\n this.graphqlManager.reactorDriveClient,\n this.viewSubject(ctx),\n );\n } else {\n createdDoc = await createEmptyDocumentResolver(\n this.reactorClient,\n {\n documentType,\n parentIdentifier,\n name,\n },\n this.graphqlManager.reactorDriveClient,\n this.viewSubject(ctx),\n );\n }\n\n // Auto-ownership: set creator as document owner\n if (ctx.user?.address && createdDoc?.id) {\n await this.documentPermissionService?.initializeDocumentProtection(\n createdDoc.id,\n ctx.user.address,\n this.authorizationService.config.defaultProtection,\n );\n }\n\n // Name fallback via SET_NAME (only for non-initialState path,\n // since initialState path sets name on header before creation)\n if (\n !initialState &&\n !preferredEditor &&\n name &&\n createdDoc.name !== name\n ) {\n const updatedDoc = await this.reactorClient.execute(\n createdDoc.id,\n \"main\",\n [setName(name)],\n undefined,\n this.viewSubject(ctx),\n );\n return toGqlPhDocument(updatedDoc);\n }\n\n return createdDoc;\n },\n createEmptyDocument: async (\n _: unknown,\n args: { parentIdentifier?: string },\n ctx: Context,\n ) => {\n let parentIdentifier = args.parentIdentifier;\n if (parentIdentifier) {\n const handle = await this.assertCanWrite(parentIdentifier, ctx);\n parentIdentifier = handle.fetchIdentifier;\n } else {\n this.assertCanCreate(ctx);\n }\n\n const result = await createEmptyDocumentResolver(\n this.reactorClient,\n {\n documentType,\n parentIdentifier,\n },\n this.graphqlManager.reactorDriveClient,\n this.viewSubject(ctx),\n );\n\n // Auto-ownership: set creator as document owner\n if (ctx.user?.address && result?.id) {\n await this.documentPermissionService?.initializeDocumentProtection(\n result.id,\n ctx.user.address,\n this.authorizationService.config.defaultProtection,\n );\n }\n\n return result;\n },\n // Generate sync and async mutations for each operation\n ...operations.reduce((mutations, op) => {\n // Sync mutation\n mutations[camelCase(op.name!)] = async (\n _: unknown,\n args: { docId: string; input: unknown },\n ctx: Context,\n ) => {\n const { docId, input } = args;\n\n const handle = await this.assertCanExecuteOperation(\n docId,\n op.name!,\n ctx,\n );\n const effectiveDocId = handle.fetchIdentifier;\n\n const doc = await this.reactorClient.get(effectiveDocId, {\n subject: this.viewSubject(ctx),\n });\n if (doc.header.documentType !== documentType) {\n throw new GraphQLError(\n `Document with id ${docId} is not of type ${documentType}`,\n );\n }\n\n const action = this.documentModel.actions[camelCase(op.name!)];\n if (!action) {\n throw new GraphQLError(`Action ${op.name} not found`);\n }\n\n try {\n const updatedDoc = await this.reactorClient.execute(\n effectiveDocId,\n \"main\",\n [action(input)],\n undefined,\n this.viewSubject(ctx),\n );\n return toGqlPhDocument(updatedDoc);\n } catch (error) {\n throw new GraphQLError(\n error instanceof Error ? error.message : `Failed to ${op.name}`,\n );\n }\n };\n\n // Async mutation - returns job ID\n mutations[`${camelCase(op.name!)}Async`] = async (\n _: unknown,\n args: { docId: string; input: unknown },\n ctx: Context,\n ) => {\n const { docId, input } = args;\n\n const handle = await this.assertCanExecuteOperation(\n docId,\n op.name!,\n ctx,\n );\n const effectiveDocId = handle.fetchIdentifier;\n\n const doc = await this.reactorClient.get(effectiveDocId, {\n subject: this.viewSubject(ctx),\n });\n if (doc.header.documentType !== documentType) {\n throw new GraphQLError(\n `Document with id ${docId} is not of type ${documentType}`,\n );\n }\n\n const action = this.documentModel.actions[camelCase(op.name!)];\n if (!action) {\n throw new GraphQLError(`Action ${op.name} not found`);\n }\n\n try {\n const jobInfo = await this.reactorClient.executeAsync(\n effectiveDocId,\n \"main\",\n [action(input)],\n );\n return jobInfo.id;\n } catch (error) {\n throw new GraphQLError(\n error instanceof Error ? error.message : `Failed to ${op.name}`,\n );\n }\n };\n\n return mutations;\n }, {} as DocumentModelResolverMap),\n },\n };\n }\n}\n","import type { DriveOwnershipCache } from \"./drive-ownership-cache.js\";\nimport type { FetchHandler } from \"./types.js\";\n\nexport type DriveFetchMiddleware = (handler: FetchHandler) => FetchHandler;\n\nconst DRIVE_ID_HEADER = \"drive-id\";\n\n/**\n * Operations that legitimately run before the target drive exists in the\n * cache. Drive creation is the obvious case (a brand-new drive cannot be\n * in the ownership set yet); other create-shaped operations that may\n * synthesize a drive must be added here too.\n */\nconst CACHE_BYPASS_OPERATIONS = new Set([\n \"createDocument\",\n \"createEmptyDocument\",\n]);\n\nconst driveIdMap = new WeakMap<globalThis.Request, string>();\n\n/** Internal — only `graphql-manager.ts` should call this. */\nexport function getRequestDriveId(\n request: globalThis.Request,\n): string | undefined {\n return driveIdMap.get(request);\n}\n\n/**\n * Returns a fetch middleware that validates the `Drive-Id` header against\n * the in-memory ownership cache. Layout:\n *\n * - No header → pass through. The LB has already round-robined; nothing\n * to validate here.\n * - Header present and drive in cache → record on the request map (for\n * the context factory to read into `context.driveId`) and pass through.\n * - Header present, drive missing, but the operation is `createDocument`\n * or `createEmptyDocument` → pass through. The drive may be in the\n * process of being created.\n * - Otherwise → return `421 Misdirected Request` with a structured body.\n * The client (or LB) can surface this as a wrong-shard signal.\n */\nexport function createDriveFetchMiddleware(\n cache: DriveOwnershipCache,\n): DriveFetchMiddleware {\n return (next: FetchHandler): FetchHandler =>\n async (request: globalThis.Request): Promise<globalThis.Response> => {\n const driveId = request.headers.get(DRIVE_ID_HEADER) ?? \"\";\n if (driveId === \"\") {\n return next(request);\n }\n\n if (cache.has(driveId)) {\n driveIdMap.set(request, driveId);\n return next(request);\n }\n\n if (await isCacheBypassOperation(request)) {\n return next(request);\n }\n\n return wrongShardResponse(driveId);\n };\n}\n\nasync function isCacheBypassOperation(\n request: globalThis.Request,\n): Promise<boolean> {\n if (request.method !== \"POST\") {\n return false;\n }\n try {\n const body = (await request.clone().json()) as {\n operationName?: unknown;\n query?: unknown;\n };\n if (typeof body.operationName === \"string\") {\n return CACHE_BYPASS_OPERATIONS.has(body.operationName);\n }\n if (typeof body.query === \"string\") {\n return CACHE_BYPASS_OPERATIONS.has(extractOperationName(body.query));\n }\n return false;\n } catch {\n return false;\n }\n}\n\nconst OPERATION_NAME_PATTERN = /\\b(?:mutation|query|subscription)\\s+(\\w+)/;\n\nfunction extractOperationName(query: string): string {\n const match = OPERATION_NAME_PATTERN.exec(query);\n return match ? match[1] : \"\";\n}\n\nfunction wrongShardResponse(driveId: string): globalThis.Response {\n return new globalThis.Response(\n JSON.stringify({ error: \"wrong-shard\", driveId }),\n {\n status: 421,\n headers: { \"content-type\": \"application/json\" },\n },\n );\n}\n","import {\n DEFAULT_DRIVE_CONTAINER_TYPES,\n type IReactorClient,\n} from \"@powerhousedao/reactor\";\n\n/**\n * In-memory record of which drives this switchboard instance owns.\n *\n * Populated at startup by walking the reactor for documents whose type is\n * listed in `DEFAULT_DRIVE_CONTAINER_TYPES` (both legacy `document-drive`\n * and `reactor-drive`). Mutated explicitly by resolver hooks after\n * successful drive create / delete operations. Read by the drive-validation\n * fetch middleware to short-circuit wrong-shard requests with a structured\n * 421 response.\n */\nexport class DriveOwnershipCache {\n private readonly drives = new Set<string>();\n\n constructor(private readonly reactorClient: IReactorClient) {}\n\n async init(): Promise<void> {\n this.drives.clear();\n for (const driveType of DEFAULT_DRIVE_CONTAINER_TYPES) {\n let page = await this.reactorClient.find({ type: driveType });\n while (true) {\n for (const drive of page.results) {\n this.drives.add(drive.header.id);\n }\n if (!page.next) {\n break;\n }\n page = await page.next();\n }\n }\n }\n\n has(driveId: string): boolean {\n return this.drives.has(driveId);\n }\n\n add(driveId: string): void {\n this.drives.add(driveId);\n }\n\n remove(driveId: string): void {\n this.drives.delete(driveId);\n }\n\n size(): number {\n return this.drives.size;\n }\n}\n","import type { GraphQLSchema } from \"graphql\";\nimport type { Request as SSERequest } from \"graphql-sse\";\nimport { createHandler } from \"graphql-sse/lib/use/fetch\";\nimport type { Context } from \"./types.js\";\n\n/**\n * Options for creating the GraphQL-over-SSE handler.\n */\nexport interface SSEHandlerOptions {\n schema: GraphQLSchema;\n /**\n * Build a GraphQL context from the incoming Fetch API Request.\n * Called once per subscription (not per event).\n *\n * The request has already passed through auth middleware by the time\n * this is invoked, so getAuthContext(request) will return the populated\n * AuthContext from the WeakMap.\n */\n contextFactory: (req: Request) => Promise<Context> | Context;\n}\n\n/**\n * Create a Fetch-API-compatible SSE handler for GraphQL subscriptions\n * using the graphql-sse library (graphql-sse protocol).\n *\n * This runs alongside the existing WebSocket (graphql-ws) transport\n * so clients can choose either protocol.\n *\n * The returned handler is a standard FetchHandler: (req: Request) => Promise<Response>.\n * It can be mounted via httpAdapter.mount() like any other handler, and auth\n * flows through the WeakMap pattern (authFetchMiddleware populates the context\n * before this handler is called).\n *\n * Clients connect via \"distinct connections mode\" (POST with\n * `Accept: text/event-stream`). Single-connection mode is disabled\n * because it adds token-management complexity with no benefit here.\n */\nexport function createGraphQLSSEHandler(\n options: SSEHandlerOptions,\n): (req: Request) => Promise<Response> {\n const { schema, contextFactory } = options;\n\n return createHandler<Context>({\n schema,\n // Returning null disables single-connection mode. All clients use\n // \"distinct connections mode\" (one POST per subscription).\n // Auth is handled upstream by authFetchMiddleware.\n authenticate: () => null,\n context: (req: SSERequest<Request>) => contextFactory(req.raw),\n });\n}\n","import type { IAnalyticsStore } from \"@powerhousedao/analytics-engine-core\";\nimport type {\n IDriveClient,\n IReactorClient,\n IRelationalDb,\n ISyncManager,\n SyncScopeGate,\n} from \"@powerhousedao/reactor\";\nimport type {\n Context,\n ISubgraph,\n SubgraphClass,\n} from \"@powerhousedao/reactor-api\";\nimport type { DocumentDriveDocument } from \"@powerhousedao/shared/document-drive\";\nimport type { DocumentModelModule } from \"@powerhousedao/shared/document-model\";\nimport type { ILogger } from \"document-model\";\nimport type { GraphQLSchema } from \"graphql\";\nimport type { IncomingHttpHeaders } from \"http\";\nimport type http from \"node:http\";\nimport path from \"node:path\";\nimport { match } from \"path-to-regexp\";\nimport type { WebSocketServer } from \"ws\";\nimport {\n CORE_PACKAGE_NAME,\n HttpRouteService,\n type IHttpScope,\n} from \"../http/index.js\";\nimport { debounce } from \"../packages/util.js\";\nimport type { AuthService, User } from \"../services/auth.service.js\";\nimport type {\n CanonicalDocumentId,\n IAuthorizationService,\n} from \"../services/authorization.service.js\";\nimport type { DocumentPermissionService } from \"../services/document-permission.service.js\";\nimport {\n buildSubgraphSchemaModule,\n createMergedSchema,\n createSchema,\n} from \"../utils/create-schema.js\";\nimport { callerSubject } from \"./base-subgraph.js\";\nimport { DocumentModelSubgraph } from \"./document-model-subgraph.js\";\nimport {\n getAuthContext,\n type AuthFetchMiddleware,\n} from \"./gateway/auth-middleware.js\";\nimport {\n createDriveFetchMiddleware,\n getRequestDriveId,\n type DriveFetchMiddleware,\n} from \"./gateway/drive-middleware.js\";\nimport { DriveOwnershipCache } from \"./gateway/drive-ownership-cache.js\";\nimport type { RequireAuthFetchMiddleware } from \"./gateway/require-auth-middleware.js\";\nimport {\n WS_CLOSE_REASON_AUTHENTICATION_REQUIRED,\n WS_CLOSE_REASON_BEARER_REJECTED,\n type FetchHandler,\n type GatewayContextFactory,\n type IGatewayAdapter,\n type IHttpAdapter,\n type AdapterRouteHandle,\n type SubgraphDefinition,\n type WsConnection,\n type WsDisposer,\n type WsHandlers,\n} from \"./gateway/types.js\";\nimport { createGraphQLSSEHandler } from \"./sse.js\";\n\nconst DOCUMENT_MODELS_TO_EXCLUDE: string[] = [];\n\n/**\n * Check if a document model has any operations with valid schemas.\n * Document models without valid operation schemas cannot generate valid subgraph schemas.\n */\nfunction hasOperationSchemas(documentModel: DocumentModelModule): boolean {\n const specification =\n documentModel.documentModel.global.specifications.at(-1);\n if (!specification) return false;\n const hasValidSchema = (schema: string | null | undefined) =>\n schema && /\\b(input|type|enum|union|interface)\\s+\\w+/.test(schema);\n return specification.modules.some((module) =>\n module.operations.some((op) => hasValidSchema(op.schema)),\n );\n}\n\n/**\n * Filter document models to keep only the latest version of each unique document model.\n */\nfunction filterLatestDocumentModelVersions(\n documentModels: DocumentModelModule[],\n): DocumentModelModule[] {\n const latestByName = new Map<string, DocumentModelModule>();\n\n for (const documentModel of documentModels) {\n const name = documentModel.documentModel.global.name;\n const existing = latestByName.get(name);\n\n if (!existing) {\n latestByName.set(name, documentModel);\n continue;\n }\n\n const currentVersion =\n documentModel.documentModel.global.specifications.at(-1)?.version ?? 0;\n const existingVersion =\n existing.documentModel.global.specifications.at(-1)?.version ?? 0;\n\n if (currentVersion > existingVersion) {\n latestByName.set(name, documentModel);\n }\n }\n\n return Array.from(latestByName.values());\n}\n\nconst DefaultFeatureFlags = {\n enableDocumentModelSubgraphs: true,\n};\n\nexport type GraphqlManagerFeatureFlags = {\n enableDocumentModelSubgraphs?: boolean;\n};\n\n/**\n * The registration-source label for document-model-generated subgraphs, so\n * they can be pruned like package-contributed ones (see\n * regenerateDocumentModelSubgraphs).\n */\nconst DOCUMENT_MODEL_SUBGRAPH_SOURCE = \"document-models\";\n\n// Returning `false` closes 4403 with the reason `Forbidden`, so every refusal\n// looks alike and a client cannot tell \"sign in\" from \"that token is no good\".\n\n// An explicit close wins over the one graphql-ws would send, and carries a\n// reason. Under `graphql-ws/use/ws` the connection is `ctx.extra`, whose\n// `socket` is the `ws` WebSocket; narrowed here so the adapters keep passing a\n// plain object through.\nfunction refuseConnection(connection: WsConnection, reason: string): false {\n const { socket } = connection as {\n socket?: { close?: (code: number, reason: string) => void };\n };\n socket?.close?.(4403, reason);\n return false;\n}\n\n// The two halves of WebSocket auth: who is connected, and whether at all.\n\n// graphql-ws calls `context` per operation and `onConnect` once per connection.\n\n// A throw from `context` closes 4500, which clients treat as fatal; 4403 retries.\n\n// So every refusal happens in `onConnect`, and `context` only reads the verdict.\n\n// Admission matches HTTP: a bad bearer is refused, an absent one is no user.\n\n// Anonymous is refused only under REQUIRE_AUTHENTICATED_CALLER, as for fetch.\n\n// WS needs its own check: `ws` owns the upgrade, so the fetch chain never runs.\n\n// Admitted anonymous connections authorize per document, as they do over SSE.\nexport function createWsAuthHandlers(opts: {\n authService?: AuthService;\n /** Whether anonymous callers are refused; read at call time, not at build time. */\n requireAuthenticatedCaller: () => boolean;\n logger: ILogger;\n buildContext: (\n connectionParams: Record<string, unknown>,\n user?: User,\n ) => Context;\n}): WsHandlers<Context> {\n const resolved = new WeakMap<WsConnection, User | undefined>();\n\n return {\n onConnect: async (connectionParams, connection) => {\n let user: User | null = null;\n\n if (opts.authService) {\n try {\n user =\n await opts.authService.authenticateWebSocketConnection(\n connectionParams,\n );\n } catch (error) {\n // `warn`: the caller sent a bad token, the server is fine.\n opts.logger.warn(\n \"Refusing WebSocket connection: @error\",\n error instanceof Error ? error.message : error,\n );\n return refuseConnection(connection, WS_CLOSE_REASON_BEARER_REJECTED);\n }\n }\n\n if (user === null && opts.requireAuthenticatedCaller()) {\n opts.logger.warn(\n \"Refusing anonymous WebSocket connection: an authenticated caller is required\",\n );\n return refuseConnection(\n connection,\n WS_CLOSE_REASON_AUTHENTICATION_REQUIRED,\n );\n }\n\n resolved.set(connection, user ?? undefined);\n return true;\n },\n\n context: (connectionParams, connection) =>\n Promise.resolve(\n opts.buildContext(connectionParams, resolved.get(connection)),\n ),\n };\n}\n\nexport class GraphQLManager {\n private initialized = false;\n private coreSubgraphsMap = new Map<string, ISubgraph[]>();\n private contextFields: Record<string, any> = {};\n private readonly subgraphs = new Map<string, ISubgraph[]>();\n\n private readonly subgraphWsDisposers = new Map<string, WsDisposer>();\n #authMiddleware: AuthFetchMiddleware | undefined;\n #requireAuthMiddleware: RequireAuthFetchMiddleware | undefined;\n #driveMiddleware: DriveFetchMiddleware | undefined;\n readonly driveOwnershipCache: DriveOwnershipCache;\n\n /** Cached document models for schema generation - updated on init and regenerate */\n private cachedDocumentModels: DocumentModelModule[] = [];\n\n private readonly subgraphHandlerCache = new Map<\n string,\n { handler: FetchHandler; subgraph: ISubgraph }\n >();\n\n /** subgraphPath → the http adapter handle of its mounted route. */\n private readonly subgraphRouteHandles = new Map<string, AdapterRouteHandle>();\n\n /** Mounted SSE routes, keyed by path: the supergraph's and each subgraph's. */\n private readonly sseRouteHandles = new Map<string, AdapterRouteHandle>();\n\n /**\n * Package name → the subgraph instances registered from it, keyed by\n * subgraph name. Tracks the package association so that removed packages\n * can be torn down (see unregisterPackage / prunePackageSubgraphs).\n */\n private readonly packageSubgraphs = new Map<string, Map<string, ISubgraph>>();\n\n /** Per-subgraph handlers by name, before auth/drive middleware is applied,\n * for in-process queries by trusted internals. */\n readonly #internalSubgraphHandlers = new Map<\n string,\n { subgraph: ISubgraph; path: string; handler: FetchHandler }\n >();\n\n /**\n * Optional reactor-drive client. When the switchboard is configured with a\n * reactor-drive container, this is provided and the resolvers dispatch to\n * it for reactor-drive parents.\n */\n readonly reactorDriveClient?: IDriveClient;\n private readonly authorizationService: IAuthorizationService;\n /** Route service in use: the injected one, or one built on first need. */\n #fallbackRoutes: HttpRouteService | undefined;\n\n constructor(\n private readonly path: string,\n private readonly httpServer: http.Server,\n private readonly wsServer: WebSocketServer,\n private readonly reactorClient: IReactorClient,\n private readonly relationalDb: IRelationalDb,\n private readonly analyticsStore: IAnalyticsStore,\n private readonly syncManager: ISyncManager,\n private readonly logger: ILogger,\n private readonly httpAdapter: IHttpAdapter,\n private readonly gatewayAdapter: IGatewayAdapter<Context>,\n private readonly authService?: AuthService,\n private readonly documentPermissionService?: DocumentPermissionService,\n private readonly featureFlags: GraphqlManagerFeatureFlags = DefaultFeatureFlags,\n private readonly port: number = 4001,\n authorizationService?: IAuthorizationService,\n reactorDriveClient?: IDriveClient,\n private readonly syncServingGate?: SyncScopeGate,\n private readonly httpRoutes?: HttpRouteService,\n ) {\n if (!authorizationService) {\n throw new Error(\"GraphQLManager requires an authorizationService\");\n }\n this.authorizationService = authorizationService;\n this.reactorDriveClient = reactorDriveClient;\n\n this.driveOwnershipCache = new DriveOwnershipCache(this.reactorClient);\n\n // Each subscription-enabled subgraph adds listeners to the shared wsServer\n // via graphql-ws's useServer(). The handler cache bounds the count, so\n // unlimited is safe here.\n this.wsServer.setMaxListeners(0);\n }\n\n async init(\n coreSubgraphs: SubgraphClass[],\n authMiddleware?: AuthFetchMiddleware,\n requireAuthMiddleware?: RequireAuthFetchMiddleware,\n ) {\n this.#authMiddleware = authMiddleware;\n this.#requireAuthMiddleware = requireAuthMiddleware;\n this.logger.debug(`Initializing Subgraph Manager...`);\n\n await this.driveOwnershipCache.init();\n this.#driveMiddleware = createDriveFetchMiddleware(\n this.driveOwnershipCache,\n );\n this.logger.debug(\n `Drive ownership cache populated with ${this.driveOwnershipCache.size()} drives`,\n );\n\n // check if Document Drive model is available\n const modulesResult = await this.reactorClient.getDocumentModelModules();\n const models = modulesResult.results;\n\n // Cache models for schema generation\n this.cachedDocumentModels = models;\n\n const driveModel = models.find(\n (it: DocumentModelModule) =>\n it.documentModel.global.name === \"DocumentDrive\",\n );\n if (!driveModel) {\n throw new Error(\"DocumentDrive model required\");\n }\n\n await this.gatewayAdapter.start(this.httpServer);\n\n this.httpAdapter.setupMiddleware({ bodyLimit: \"50mb\" });\n\n // Register REST endpoint for drive info as a framework-agnostic FetchHandler.\n // posix.join, not join: these are URL routes, and on Windows path.join\n // would emit backslashes, mounting the route at \"\\d\\:drive\" so every\n // request 404s.\n const driveRoutePath = path.posix.join(this.path, \"d/:drive\");\n const driveMatcher = match<{ drive: string }>(driveRoutePath);\n const driveInfoHandler = async (request: Request): Promise<Response> => {\n const url = new URL(request.url);\n const matched = driveMatcher(url.pathname);\n const driveIdOrSlug = matched ? matched.params.drive : undefined;\n\n if (!driveIdOrSlug) {\n return Response.json(\n { error: \"Drive ID or slug is required\" },\n { status: 400 },\n );\n }\n\n const user = getAuthContext(request)?.user;\n try {\n // Read as the caller, so a drive whose domain it may not read serves\n // its header alone; discovery must still reach graphqlEndpoint.\n const driveDoc = await this.reactorClient.get<DocumentDriveDocument>(\n driveIdOrSlug,\n { subject: callerSubject(user) },\n );\n\n // Drive metadata is a document read, so it answers to the same\n // authorization as every GraphQL read (`assertCanReadCanonical`).\n // 404 rather than 403: a caller who may not read the drive must not\n // be able to tell \"protected\" from \"does not exist\" by probing slugs.\n const canRead = await this.authorizationService.canRead(\n driveDoc.header.id as CanonicalDocumentId,\n user?.address,\n );\n if (!canRead) {\n this.logger.debug(`Drive read refused: ${driveIdOrSlug}`);\n return Response.json({ error: \"Drive not found\" }, { status: 404 });\n }\n\n const forwardedProto = request.headers\n .get(\"x-forwarded-proto\")\n ?.split(\",\")[0]\n .trim();\n const protocol =\n (forwardedProto ?? url.protocol.replace(\":\", \"\")) + \":\";\n const forwardedHost = request.headers\n .get(\"x-forwarded-host\")\n ?.split(\",\")[0]\n .trim();\n const host = forwardedHost ?? request.headers.get(\"host\") ?? \"\";\n const forwardedPrefix =\n request.headers\n .get(\"x-forwarded-prefix\")\n ?.split(\",\")[0]\n .trim()\n .replace(/\\/$/, \"\") ?? \"\";\n const localBase = this.path === \"/\" ? \"\" : this.path;\n const basePath = forwardedPrefix + localBase;\n const graphqlEndpoint = `${protocol}//${host}${basePath}/graphql/r`;\n\n // Absent when the gate stripped it.\n const global = (driveDoc.state as Partial<typeof driveDoc.state>)\n .global;\n return Response.json({\n id: driveDoc.header.id,\n slug: driveDoc.header.slug,\n meta: driveDoc.header.meta,\n name: global?.name || driveDoc.header.name,\n icon: global?.icon ?? undefined,\n ...(graphqlEndpoint && { graphqlEndpoint }),\n });\n } catch (error: unknown) {\n this.logger.debug(`Drive not found: ${driveIdOrSlug}`, error);\n return Response.json({ error: \"Drive not found\" }, { status: 404 });\n }\n };\n\n // Identity resolution only — deliberately not the full\n // `#composeFetchMiddleware` chain. Drive discovery is the one read a\n // client makes before it can authenticate anything: Connect reads\n // `graphqlEndpoint` from here to register the sync remote, so a blanket\n // require-auth gate would leave an anonymous caller unable to ever reach\n // the authenticated surface. The bearer is read when present (an invalid\n // one is still a 401 from the auth middleware) and the drive is then\n // authorized individually, above. The drive-shard middleware is skipped\n // too: any healthy backend can answer this route.\n this.httpAdapter.mount(\n driveRoutePath,\n this.#authMiddleware\n ? this.#authMiddleware(driveInfoHandler)\n : driveInfoHandler,\n );\n this.logger.info(`Registered REST endpoint: GET ${driveRoutePath}`);\n\n await this.#setupCoreSubgraphs(\"graphql\", coreSubgraphs);\n\n if (this.featureFlags.enableDocumentModelSubgraphs) {\n await this.#setupDocumentModelSubgraphs(\"graphql\", models);\n }\n\n await this.#createSupergraphGateway();\n\n return this.updateRouter();\n }\n\n /**\n * Regenerate document model subgraphs when models are dynamically loaded.\n * Fetches current modules from reactor client (source of truth).\n */\n async regenerateDocumentModelSubgraphs(): Promise<void> {\n if (!this.featureFlags.enableDocumentModelSubgraphs) {\n return;\n }\n\n try {\n const modulesResult = await this.reactorClient.getDocumentModelModules();\n const models = modulesResult.results;\n\n // Update cached models for schema generation\n this.cachedDocumentModels = models;\n\n const registeredNames = await this.#setupDocumentModelSubgraphs(\n \"graphql\",\n models,\n );\n // A model removed since the last regeneration (e.g. its package was\n // uninstalled) must lose its subgraph; replacing alone would keep it.\n await this.prunePackageSubgraphs(\n DOCUMENT_MODEL_SUBGRAPH_SOURCE,\n registeredNames,\n );\n await this.updateRouter();\n this.logger.info(\n \"Regenerated document model subgraphs with @count models\",\n models.length,\n );\n } catch (error) {\n this.logger.error(\n \"Failed to regenerate document model subgraphs: @error\",\n error,\n );\n throw error;\n }\n }\n\n async #setupCoreSubgraphs(\n supergraph: string,\n coreSubgraphs: SubgraphClass[],\n ) {\n for (const subgraph of coreSubgraphs) {\n try {\n await this.registerSubgraph(subgraph, supergraph, true);\n } catch (error) {\n this.logger.error(\n `Failed to setup core subgraph ${subgraph.name}`,\n error,\n );\n }\n }\n\n return this.#setupSubgraphs(this.coreSubgraphsMap);\n }\n\n async #setupDocumentModelSubgraphs(\n supergraph: string,\n documentModels: DocumentModelModule[],\n ): Promise<Set<string>> {\n const latestDocumentModels =\n filterLatestDocumentModelVersions(documentModels);\n const registeredNames = new Set<string>();\n\n for (const documentModel of latestDocumentModels) {\n if (\n DOCUMENT_MODELS_TO_EXCLUDE.includes(\n documentModel.documentModel.global.id,\n )\n ) {\n continue;\n }\n if (!hasOperationSchemas(documentModel)) {\n continue;\n }\n try {\n const subgraphInstance = new DocumentModelSubgraph(documentModel, {\n http: this.scopeForPackage(CORE_PACKAGE_NAME),\n relationalDb: this.relationalDb,\n analyticsStore: this.analyticsStore,\n reactorClient: this.reactorClient,\n graphqlManager: this,\n syncManager: this.syncManager,\n path: this.path,\n documentPermissionService: this.documentPermissionService,\n authorizationService: this.authorizationService,\n syncServingGate: this.syncServingGate,\n });\n\n await this.#addSubgraphInstance(\n subgraphInstance,\n supergraph,\n false,\n DOCUMENT_MODEL_SUBGRAPH_SOURCE,\n );\n registeredNames.add(subgraphInstance.name);\n } catch (error) {\n this.logger.error(\n `Failed to setup document model subgraph for ${documentModel.documentModel.global.id}`,\n error instanceof Error ? error.message : error,\n );\n this.logger.debug(\"@error\", error);\n }\n }\n\n // Document model subgraph instances are added to this.subgraphs above.\n // Their handlers are wired in _updateRouter() → #setupSubgraphs(this.subgraphs),\n // which is called at the end of init() via updateRouter(). We intentionally do\n // NOT call #setupSubgraphs(this.coreSubgraphsMap) here - doing so would\n // create duplicate Apollo servers for the same core-subgraph schemas, which\n // in the new IGatewayAdapter architecture hangs #waitForServer and blocks init().\n\n return registeredNames;\n }\n\n /** Core subgraph names are reserved: they register with core=true during\n * init() and no package subgraph may take one of their names. */\n #isCoreNameReserved(name: string): boolean {\n for (const subgraphs of this.coreSubgraphsMap.values()) {\n if (subgraphs.some((it) => it.name === name)) return true;\n }\n return false;\n }\n\n async #addSubgraphInstance(\n subgraphInstance: ISubgraph,\n supergraph = \"\",\n core = false,\n packageName?: string,\n ) {\n // A package subgraph may not take a name a core subgraph has registered:\n // the in-process handler map is keyed by bare name, so a same-name\n // subgraph would shadow the core one (issue #2972). Reject rather than\n // throw - package registration runs from a detached async closure in\n // server.ts, where a throw is an unhandled rejection that takes the\n // host down.\n if (!core && this.#isCoreNameReserved(subgraphInstance.name)) {\n this.logger.error(\n \"Rejecting subgraph @name: name is reserved by a registered core subgraph\",\n subgraphInstance.name,\n );\n return undefined;\n }\n\n const subgraphsMap = core ? this.coreSubgraphsMap : this.subgraphs;\n\n const existingSubgraph = subgraphsMap\n .get(supergraph)\n ?.find((it) => it.name === subgraphInstance.name);\n\n // Re-registering the same instance is a no-op.\n if (existingSubgraph === subgraphInstance) {\n this.logger.debug(\n `Skipping duplicate subgraph: ${subgraphInstance.name}`,\n );\n return existingSubgraph;\n }\n\n // Same name, different instance: replace (e.g. package hot-reload).\n if (existingSubgraph) {\n await this.#removeSubgraphInstance(existingSubgraph);\n }\n\n await subgraphInstance.onSetup?.();\n\n const subgraphs = subgraphsMap.get(supergraph) ?? [];\n subgraphs.push(subgraphInstance);\n subgraphsMap.set(supergraph, subgraphs);\n\n if (supergraph !== \"\" && supergraph !== \"graphql\") {\n subgraphsMap.get(\"graphql\")?.push(subgraphInstance);\n }\n\n if (packageName !== undefined) {\n let byName = this.packageSubgraphs.get(packageName);\n if (!byName) {\n byName = new Map();\n this.packageSubgraphs.set(packageName, byName);\n }\n byName.set(subgraphInstance.name, subgraphInstance);\n }\n this.logger.info(\n `${existingSubgraph ? \"Replaced\" : \"Registered\"} ${this.path.endsWith(\"/\") ? this.path : this.path + \"/\"}${supergraph ? supergraph + \"/\" : \"\"}${subgraphInstance.name} subgraph.`,\n );\n return subgraphInstance;\n }\n\n /**\n * Tear down a subgraph instance: disconnect it, drop it from every\n * bucket, unmount its route, dispose its WebSocket handler, and remove\n * its internal handler. Used when a subgraph is replaced or its package\n * is removed; #setupSubgraphs then never re-mounts it.\n */\n async #removeSubgraphInstance(instance: ISubgraph) {\n try {\n await instance.onDisconnect?.();\n } catch (error) {\n this.logger.error(\n \"Error disconnecting subgraph @name: @error\",\n instance.name,\n error,\n );\n }\n\n for (const subgraphsMap of [this.coreSubgraphsMap, this.subgraphs]) {\n for (const [bucket, subgraphs] of subgraphsMap.entries()) {\n if (!subgraphs.includes(instance)) {\n continue;\n }\n subgraphsMap.set(\n bucket,\n subgraphs.filter((it) => it !== instance),\n );\n\n const subgraphPath = this.#getSubgraphPath(instance, bucket);\n this.subgraphHandlerCache.delete(subgraphPath);\n\n const routeHandle = this.subgraphRouteHandles.get(subgraphPath);\n if (routeHandle !== undefined) {\n routeHandle.dispose();\n this.subgraphRouteHandles.delete(subgraphPath);\n }\n this.#disposeSSERoute(subgraphPath);\n\n const wsDisposer = this.subgraphWsDisposers.get(subgraphPath);\n if (wsDisposer) {\n this.subgraphWsDisposers.delete(subgraphPath);\n try {\n await wsDisposer.dispose();\n } catch (error) {\n this.logger.error(\n \"Error disposing subgraph websocket @name: @error\",\n instance.name,\n error,\n );\n }\n }\n }\n }\n\n const internalHandler = this.#internalSubgraphHandlers.get(instance.name);\n if (internalHandler?.subgraph === instance) {\n this.#internalSubgraphHandlers.delete(instance.name);\n }\n\n for (const [packageName, byName] of this.packageSubgraphs) {\n if (byName.get(instance.name) !== instance) continue;\n byName.delete(instance.name);\n if (byName.size === 0) {\n this.packageSubgraphs.delete(packageName);\n }\n }\n }\n\n /**\n * Register a pre-constructed subgraph instance.\n * Use this when you need to pass custom dependencies to a subgraph.\n */\n async registerSubgraphInstance(\n subgraphInstance: ISubgraph,\n supergraph = \"\",\n core = false,\n ) {\n return this.#addSubgraphInstance(subgraphInstance, supergraph, core);\n }\n\n /**\n * Get the base path used for subgraph registration.\n */\n getBasePath(): string {\n return this.path;\n }\n\n /**\n * Get the authorization service shared with subgraphs. Use this when\n * constructing a subgraph instance externally for\n * {@link registerSubgraphInstance}.\n */\n getAuthorizationService(): IAuthorizationService {\n return this.authorizationService;\n }\n\n /**\n * The HTTP scope a package's subgraphs get. Falls back to a scope over a\n * throwaway service when route hosting is not configured, so a subgraph can\n * always rely on `args.http` existing.\n */\n scopeForPackage(packageName: string): IHttpScope {\n this.#fallbackRoutes ??=\n this.httpRoutes ??\n new HttpRouteService({\n httpAdapter: this.httpAdapter,\n basePath: this.path,\n authService: this.authService,\n });\n // Non-throwing: a package key with no usable name yields a scope that\n // refuses registrations, rather than taking the host down at boot.\n return this.#fallbackRoutes.scopeForOrNull(packageName);\n }\n\n /**\n * Register a subgraph class. `packageName` labels the resulting instance\n * with its contributing package so the instance can be torn down when the\n * package is removed or drops the subgraph (see unregisterPackage and\n * prunePackageSubgraphs), and decides the namespace its REST routes and\n * webhooks live under.\n */\n async registerSubgraph(\n subgraph: SubgraphClass,\n supergraph = \"\",\n core = false,\n packageName?: string,\n ) {\n const subgraphInstance = new subgraph({\n // Left undefined, the subgraph is core rather than contributed, and its\n // routes hang off reactor-api's own namespace. Not defaulted in the\n // parameter, because `undefined` is what keeps a core subgraph out of\n // `packageSubgraphs` and so out of package teardown.\n http: this.scopeForPackage(packageName ?? CORE_PACKAGE_NAME),\n relationalDb: this.relationalDb,\n analyticsStore: this.analyticsStore,\n reactorClient: this.reactorClient,\n graphqlManager: this,\n syncManager: this.syncManager,\n path: this.path,\n documentPermissionService: this.documentPermissionService,\n authorizationService: this.authorizationService,\n syncServingGate: this.syncServingGate,\n });\n\n return this.#addSubgraphInstance(\n subgraphInstance,\n supergraph,\n core,\n packageName,\n );\n }\n\n /**\n * Tear down every subgraph instance registered from `packageName`:\n * disconnects the instances, unmounts their routes, disposes their\n * WebSocket handlers, then refreshes the router so the supergraph SDL and\n * the supergraph SSE handler no longer reference them. No-op if the\n * package has no registered subgraphs.\n */\n async unregisterPackage(packageName: string): Promise<void> {\n // Routes and webhooks belong to the package, not to its subgraphs, so this\n // runs before the early return below: a package may contribute a processor\n // that registers routes and no subgraph at all, and its routes still have\n // to go. A route that outlives its package answers against unloaded code.\n this.#disposeHttpScope(packageName);\n\n const byName = this.packageSubgraphs.get(packageName);\n if (!byName || byName.size === 0) return;\n for (const instance of Array.from(byName.values())) {\n await this.#removeSubgraphInstance(instance);\n }\n await this.updateRouter();\n }\n\n /**\n * Releases the package's HTTP scope: every route it mounted, and its webhook\n * registrations. Idempotent, and silent for a package that never had one.\n */\n #disposeHttpScope(packageName: string): void {\n const routes = this.#fallbackRoutes ?? this.httpRoutes;\n try {\n routes?.disposeScope(packageName);\n } catch (error) {\n // Teardown must not be the thing that fails: a package whose name never\n // resolved to a namespace has nothing mounted to release anyway.\n this.logger.warn(\n `Failed to release HTTP routes for \"${packageName}\": @error`,\n error,\n );\n }\n }\n\n /**\n * Remove this package's registered subgraphs whose names are not in\n * `keepNames` — the package is still loaded but dropped some of its\n * subgraphs. Refreshes the router if anything was removed.\n */\n async prunePackageSubgraphs(\n packageName: string,\n keepNames: ReadonlySet<string>,\n ): Promise<void> {\n const byName = this.packageSubgraphs.get(packageName);\n if (!byName) return;\n let removed = 0;\n for (const [name, instance] of Array.from(byName.entries())) {\n if (!keepNames.has(name)) {\n await this.#removeSubgraphInstance(instance);\n removed++;\n }\n }\n if (removed > 0) {\n await this.updateRouter();\n }\n }\n\n /** Find a registered subgraph by name, core or package-contributed. */\n getSubgraphByName(name: string): ISubgraph | undefined {\n for (const subgraphs of [\n ...this.coreSubgraphsMap.values(),\n ...this.subgraphs.values(),\n ]) {\n const found = subgraphs.find((subgraph) => subgraph.name === name);\n if (found) {\n return found;\n }\n }\n return undefined;\n }\n\n /** Whether a registered subgraph has a live handler, i.e. whether\n * {@link executeSubgraphQuery} can reach it right now. */\n hasSubgraphHandler(name: string): boolean {\n return this.#internalSubgraphHandlers.has(name);\n }\n\n /** Run a query against one registered subgraph in-process: the subgraph's own\n * handler, without a socket or the auth/drive middleware. Trusted callers. */\n async executeSubgraphQuery<T>(\n subgraphName: string,\n query: string,\n variables: Record<string, unknown>,\n ): Promise<T> {\n const entry = this.#internalSubgraphHandlers.get(subgraphName);\n if (!entry) {\n throw new Error(\n this.getSubgraphByName(subgraphName)\n ? `Subgraph \"${subgraphName}\" is registered but has no handler yet`\n : `Subgraph \"${subgraphName}\" is not registered`,\n );\n }\n\n // Address the subgraph at its real mount path so resolvers and plugins that\n // read the request URL see what an external caller would.\n const url = new URL(entry.path, `http://localhost:${this.port}/`);\n const response = await entry.handler(\n new Request(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n },\n body: JSON.stringify({ query, variables }),\n }),\n );\n if (!response.ok) {\n // Keep the body: Apollo reports validation failures as a 400 whose only\n // description of what went wrong is in there.\n const detail = await response.text().catch(() => \"\");\n throw new Error(\n `Subgraph \"${subgraphName}\" query failed: ${response.status}${\n detail ? ` ${detail}` : \"\"\n }`,\n );\n }\n\n const body = (await response.json()) as {\n data?: T;\n errors?: { message: string }[];\n };\n if (body.errors?.length) {\n throw new Error(body.errors.map((error) => error.message).join(\"; \"));\n }\n if (!body.data) {\n throw new Error(`Subgraph \"${subgraphName}\" returned no data`);\n }\n return body.data;\n }\n\n updateRouter = debounce(this._updateRouter.bind(this), 1000);\n\n private async _updateRouter() {\n this.logger.debug(\"Updating router\");\n\n await this.#setupSubgraphs(this.subgraphs);\n\n try {\n await this.gatewayAdapter.updateSupergraph();\n this.logger.debug(\"Updated Apollo Gateway supergraph\");\n } catch (error) {\n this.logger.error(\n \"Failed to update Apollo Gateway supergraph: @error\",\n error,\n );\n }\n\n // Refresh the supergraph-level SSE handler so it picks up\n // any newly registered subscription-enabled subgraphs.\n const superGraphPath = path.posix.join(this.path, \"graphql\");\n this.#setupSupergraphSSE(superGraphPath);\n }\n\n getAdditionalContextFields = () => {\n return this.contextFields;\n };\n\n setAdditionalContextFields(fields: Record<string, any>) {\n this.contextFields = { ...this.contextFields, ...fields };\n }\n\n #makeContextFactory(): GatewayContextFactory<Context> {\n return (request: Request): Promise<Context> => {\n const authCtx = getAuthContext(request);\n const driveId = getRequestDriveId(request);\n const headers: IncomingHttpHeaders = {};\n request.headers.forEach((v, k) => {\n headers[k] = v;\n });\n return Promise.resolve<Context>({\n headers,\n db: this.relationalDb,\n ...this.getAdditionalContextFields(),\n driveId,\n user: authCtx?.user,\n });\n };\n }\n\n #makeWsContextFactory(): WsHandlers<Context> {\n return createWsAuthHandlers({\n authService: this.authService,\n // Read at call time: init() installs this after the manager is built.\n requireAuthenticatedCaller: () =>\n this.#requireAuthMiddleware !== undefined,\n logger: this.logger,\n buildContext: (connectionParams, user) => {\n const context: Context = {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n headers: connectionParams as any,\n db: this.relationalDb,\n ...this.getAdditionalContextFields(),\n };\n if (user) context.user = user;\n return context;\n },\n });\n }\n\n setSupergraph(supergraph: string, subgraphs: ISubgraph[]) {\n // setSupergraph bypasses #addSubgraphInstance, so apply the same\n // reserved-name guard here: drop incoming subgraphs that would shadow a\n // registered core subgraph, keep the rest.\n const accepted: ISubgraph[] = [];\n for (const subgraph of subgraphs) {\n if (this.#isCoreNameReserved(subgraph.name)) {\n this.logger.error(\n \"Rejecting subgraph @name: name is reserved by a registered core subgraph\",\n subgraph.name,\n );\n continue;\n }\n accepted.push(subgraph);\n }\n this.subgraphs.set(supergraph, accepted);\n const globalSubgraphs = this.subgraphs.get(\"graphql\");\n if (globalSubgraphs) {\n this.subgraphs.set(\"graphql\", [...globalSubgraphs, ...accepted]);\n } else {\n this.subgraphs.set(\"graphql\", accepted);\n }\n return this.updateRouter();\n }\n\n async shutdown(): Promise<void> {\n this.logger.info(\"Shutting down GraphQL Manager\");\n\n // Dispose per-subgraph WebSocket handlers before closing the WS server.\n for (const disposer of this.subgraphWsDisposers.values()) {\n await disposer.dispose();\n }\n this.subgraphWsDisposers.clear();\n\n // Stop all Apollo servers (per-subgraph + federation gateway) via the adapter.\n await this.gatewayAdapter.stop();\n\n return new Promise((resolve) => {\n this.wsServer.close(() => {\n this.logger.info(\"WebSocket server closed\");\n resolve();\n });\n });\n }\n\n // The mount path is owned by the host: the manager's base path, never the\n // subgraph's own `path` field, which a package subgraph can overwrite with a\n // field initializer (it runs after super()).\n #getSubgraphPath(subgraph: ISubgraph, supergraph: string) {\n return path.posix.join(this.path, supergraph, subgraph.name);\n }\n\n /** The in-process handler map is keyed by bare name, so two distinct\n * subgraphs sharing one name would shadow each other: keep the first. */\n #setInternalSubgraphHandler(\n subgraph: ISubgraph,\n subgraphPath: string,\n handler: FetchHandler,\n ) {\n const existing = this.#internalSubgraphHandlers.get(subgraph.name);\n if (existing && existing.subgraph !== subgraph) {\n this.logger.warn(\n \"Two subgraphs are named @name (@kept and @ignored); in-process queries keep the first\",\n subgraph.name,\n existing.path,\n subgraphPath,\n );\n return;\n }\n this.#internalSubgraphHandlers.set(subgraph.name, {\n subgraph,\n path: subgraphPath,\n handler,\n });\n }\n\n async #setupSubgraphs(subgraphsMap: Map<string, ISubgraph[]>) {\n for (const [supergraph, subgraphs] of subgraphsMap.entries()) {\n for (const subgraph of subgraphs) {\n this.logger.debug(`Setting up subgraph ${subgraph.name}`);\n const subgraphPath = this.#getSubgraphPath(subgraph, supergraph);\n try {\n // Skip if handler already cached and mounted — a replaced subgraph\n // invalidates its entries, so a cached path is current. Two\n // different subgraphs landing on the same path: first mounted\n // wins; say so.\n const cached = this.subgraphHandlerCache.get(subgraphPath);\n if (cached) {\n if (cached.subgraph !== subgraph) {\n this.logger.warn(\n \"Subgraph path @path already mounted by @kept; @name is shadowed and will not be mounted\",\n subgraphPath,\n cached.subgraph.name,\n subgraph.name,\n );\n }\n continue;\n }\n\n const schema = createSchema(\n this.cachedDocumentModels,\n subgraph.resolvers,\n subgraph.typeDefs,\n );\n\n const rawHandler = await this.gatewayAdapter.createHandler(\n schema,\n this.#makeContextFactory(),\n );\n const fetchHandler = this.#composeFetchMiddleware(rawHandler);\n this.subgraphHandlerCache.set(subgraphPath, {\n handler: fetchHandler,\n subgraph,\n });\n this.#setInternalSubgraphHandler(subgraph, subgraphPath, rawHandler);\n this.subgraphRouteHandles.set(\n subgraphPath,\n this.httpAdapter.mount(subgraphPath, fetchHandler),\n );\n\n if (subgraph.hasSubscriptions) {\n try {\n const existingDisposer =\n this.subgraphWsDisposers.get(subgraphPath);\n if (existingDisposer) {\n this.logger.warn(\n \"Overwriting existing WebSocket disposer for subgraph at path @path\",\n subgraphPath,\n );\n }\n const wsDisposer = this.gatewayAdapter.attachWebSocket(\n this.wsServer,\n schema,\n this.#makeWsContextFactory(),\n );\n this.subgraphWsDisposers.set(subgraphPath, wsDisposer);\n this.logger.debug(\n `WebSocket subscriptions enabled for ${subgraph.name}`,\n );\n } catch (error) {\n this.logger.error(\n \"Failed to setup websocket for subgraph @name at path @path: @error\",\n subgraph.name,\n subgraphPath,\n error,\n );\n }\n\n // Set up SSE (Server-Sent Events) transport alongside WebSocket.\n // Clients can use SSE by sending POST requests with\n // Accept: text/event-stream to the /stream sub-path.\n try {\n this.#setupSSEHandler(schema, subgraphPath);\n this.logger.debug(\n `SSE subscriptions enabled for ${subgraph.name}`,\n );\n } catch (error) {\n this.logger.error(\n \"Failed to setup SSE for subgraph @name at path @path: @error\",\n subgraph.name,\n subgraphPath,\n error,\n );\n }\n }\n } catch (error) {\n this.logger.error(\n \"Failed to setup subgraph @name at path @path: @error\",\n subgraph.name,\n subgraphPath,\n error,\n );\n }\n }\n }\n }\n\n #getAllSubgraphs() {\n const subgraphsMap = new Map<string, ISubgraph>();\n for (const [supergraph, subgraphs] of [\n ...this.coreSubgraphsMap.entries(),\n ...this.subgraphs.entries(),\n ]) {\n if (supergraph === \"\") {\n continue;\n }\n\n for (const subgraph of subgraphs) {\n const subgraphPath = this.#getSubgraphPath(subgraph, supergraph);\n subgraphsMap.set(subgraphPath, subgraph);\n }\n }\n return subgraphsMap;\n }\n\n #buildSubgraphSchemaModule(subgraph: ISubgraph) {\n return buildSubgraphSchemaModule(\n this.cachedDocumentModels,\n subgraph.resolvers,\n subgraph.typeDefs,\n );\n }\n\n #getSubgraphDefinitions(): SubgraphDefinition[] {\n const subgraphs = this.#getAllSubgraphs();\n\n const herokuOrLocal = process.env.HEROKU_APP_DEFAULT_DOMAIN_NAME\n ? `https://${process.env.HEROKU_APP_DEFAULT_DOMAIN_NAME}`\n : `http://localhost:${this.port}`;\n\n return Array.from(subgraphs.entries()).map(([subgraphPath, subgraph]) => {\n const module = this.#buildSubgraphSchemaModule(subgraph);\n return {\n name: subgraphPath.replace(\"/\", \":\"),\n typeDefs: module.typeDefs,\n // In-process form: the stitching adapter merges these resolvers into\n // the supergraph; federation adapters ignore the field.\n resolvers: module.resolvers,\n url: `${herokuOrLocal}${subgraphPath}`,\n };\n });\n }\n\n async #createSupergraphGateway() {\n const superGraphPath = path.posix.join(this.path, \"graphql\");\n const rawHandler: FetchHandler =\n await this.gatewayAdapter.createSupergraphHandler(\n () => this.#getSubgraphDefinitions(),\n this.httpServer,\n this.#makeContextFactory(),\n );\n const fetchHandler = this.#composeFetchMiddleware(rawHandler);\n this.httpAdapter.mount(superGraphPath, fetchHandler);\n\n // Set up SSE subscriptions at the supergraph level (/graphql/stream).\n // Build a subscription schema from all subgraphs that define subscriptions.\n this.#setupSupergraphSSE(superGraphPath);\n\n if (!this.initialized) {\n this.logger.info(`Registered ${superGraphPath} supergraph `);\n this.initialized = true;\n }\n return;\n }\n\n /**\n * Set up an SSE subscription endpoint at the supergraph level.\n * Merges the schemas of all subscription-enabled subgraphs so that\n * clients can subscribe at /graphql/stream without knowing individual\n * subgraph paths.\n */\n #setupSupergraphSSE(superGraphPath: string) {\n const allSubgraphs = this.#getAllSubgraphs();\n\n const modules = Array.from(allSubgraphs.values())\n .filter((subgraph) => subgraph.hasSubscriptions)\n .map((subgraph) => this.#buildSubgraphSchemaModule(subgraph));\n\n if (modules.length === 0) {\n // No subscription-capable subgraphs left: drop the SSE route rather\n // than keep serving an empty merged schema.\n this.#disposeSSERoute(superGraphPath);\n return;\n }\n\n try {\n const mergedSchema = createMergedSchema(modules);\n this.#setupSSEHandler(mergedSchema, superGraphPath);\n this.logger.debug(\n `SSE subscriptions enabled at supergraph level (merged from ${modules.length} subgraph(s))`,\n );\n } catch (error) {\n this.logger.error(\"Failed to setup supergraph SSE: @error\", error);\n }\n }\n\n /**\n * Set up a GraphQL-over-SSE handler at `<basePath>/stream`.\n *\n * Clients subscribe by sending a POST with `Accept: text/event-stream`\n * to the `/stream` sub-path. Authentication is handled by the normal\n * Express middleware (Authorization header), unlike WebSocket which\n * needs its own connectionParams-based auth.\n */\n #setupSSEHandler(schema: GraphQLSchema, basePath: string) {\n const ssePath = basePath + \"/stream\";\n const rawHandler = createGraphQLSSEHandler({\n schema,\n contextFactory: this.#makeContextFactory(),\n });\n const handler = this.#composeFetchMiddleware(rawHandler);\n // Re-created on every router update: replace this path's previous route\n // rather than pile another on top of it, and leave other paths' alone.\n this.#disposeSSERoute(basePath);\n this.sseRouteHandles.set(\n ssePath,\n this.httpAdapter.mount(ssePath, handler, { exact: true }),\n );\n }\n\n #disposeSSERoute(basePath: string): void {\n const ssePath = basePath + \"/stream\";\n const handle = this.sseRouteHandles.get(ssePath);\n if (handle !== undefined) {\n handle.dispose();\n this.sseRouteHandles.delete(ssePath);\n }\n }\n\n /**\n * Compose the request-level fetch middleware chain. Auth runs first\n * (so we don't validate shard before knowing the request is even\n * authorized); the require-authenticated-caller middleware runs next,\n * before shard validation, so an anonymous caller is rejected with a\n * 401 rather than a 421; drive-ownership validation runs last.\n */\n #composeFetchMiddleware(rawHandler: FetchHandler): FetchHandler {\n let handler = rawHandler;\n if (this.#driveMiddleware) {\n handler = this.#driveMiddleware(handler);\n }\n if (this.#requireAuthMiddleware) {\n handler = this.#requireAuthMiddleware(handler);\n }\n if (this.#authMiddleware) {\n handler = this.#authMiddleware(handler);\n }\n return handler;\n }\n}\n","import { GraphQLError } from \"graphql\";\nimport type { IAuthorizationService } from \"../../services/authorization.service.js\";\nimport type { PackageManagementService } from \"../../services/package-management.service.js\";\nimport type { InstalledPackageInfo } from \"../../services/package-storage.js\";\nimport type { Context } from \"../types.js\";\n\nfunction requireAdmin(\n authorizationService: IAuthorizationService,\n ctx: Context,\n): void {\n if (!authorizationService.isSupremeAdmin(ctx.user?.address)) {\n throw new GraphQLError(\"Admin access required\");\n }\n}\n\nfunction formatPackageInfo(info: InstalledPackageInfo) {\n return {\n name: info.name,\n version: info.version ?? null,\n registryUrl: info.registryUrl,\n installedAt: info.installedAt.toISOString(),\n documentTypes: info.documentTypes,\n };\n}\n\nexport async function installedPackages(\n service: PackageManagementService,\n): Promise<ReturnType<typeof formatPackageInfo>[]> {\n const packages = await service.getInstalledPackages();\n return packages.map(formatPackageInfo);\n}\n\nexport async function installedPackage(\n service: PackageManagementService,\n args: { name: string },\n): Promise<ReturnType<typeof formatPackageInfo> | null> {\n const pkg = await service.getInstalledPackage(args.name);\n return pkg ? formatPackageInfo(pkg) : null;\n}\n\nexport async function installPackage(\n service: PackageManagementService,\n authorizationService: IAuthorizationService,\n args: { name: string; registryUrl?: string | null },\n ctx: Context,\n): Promise<{\n package: ReturnType<typeof formatPackageInfo>;\n documentModelsLoaded: number;\n}> {\n requireAdmin(authorizationService, ctx);\n\n const result = await service.installPackage(\n args.name,\n args.registryUrl ?? undefined,\n );\n\n return {\n package: formatPackageInfo(result.package),\n documentModelsLoaded: result.documentModelsLoaded,\n };\n}\n\nexport async function uninstallPackage(\n service: PackageManagementService,\n authorizationService: IAuthorizationService,\n args: { name: string },\n ctx: Context,\n): Promise<boolean> {\n requireAdmin(authorizationService, ctx);\n\n return service.uninstallPackage(args.name);\n}\n","\"# Packages Subgraph Schema\\n# Provides operations for runtime package management\\n\\nscalar DateTime\\n\\n# Information about an installed package\\ntype InstalledPackage {\\n # Package name (e.g., \\\"@powerhousedao/vetra\\\")\\n name: String!\\n # Package version if known\\n version: String\\n # Registry URL where the package was installed from\\n registryUrl: String!\\n # Timestamp when the package was installed\\n installedAt: DateTime!\\n # Document type IDs provided by this package\\n documentTypes: [String!]!\\n}\\n\\n# Result returned after installing a package\\ntype InstallPackageResult {\\n # The installed package information\\n package: InstalledPackage!\\n # Number of document models loaded from the package\\n documentModelsLoaded: Int!\\n}\\n\\ntype PackagesQueries {\\n # Get all installed packages\\n installedPackages: [InstalledPackage!]!\\n\\n # Get information about a specific installed package\\n installedPackage(name: String!): InstalledPackage\\n}\\n\\ntype PackagesMutations {\\n # Install a package from the registry (requires admin access)\\n installPackage(\\n # Package name (e.g., \\\"@powerhousedao/vetra\\\")\\n name: String!\\n # Registry URL (uses default if not provided)\\n registryUrl: String\\n ): InstallPackageResult!\\n\\n # Uninstall a package (requires admin access)\\n uninstallPackage(\\n # Package name to uninstall\\n name: String!\\n ): Boolean!\\n}\\n\\ntype Query {\\n Packages: PackagesQueries!\\n}\\n\\ntype Mutation {\\n Packages: PackagesMutations!\\n}\\n\"","import { ConsoleLogger } from \"document-model\";\nimport { gql } from \"graphql-tag\";\nimport type { PackageManagementService } from \"../../services/package-management.service.js\";\nimport { BaseSubgraph } from \"../base-subgraph.js\";\nimport type { Context, SubgraphArgs } from \"../types.js\";\nimport * as resolvers from \"./resolvers.js\";\nimport schemaSource from \"./schema.graphql\";\n\nexport interface PackagesSubgraphArgs extends SubgraphArgs {\n packageManagementService: PackageManagementService;\n}\n\nexport class PackagesSubgraph extends BaseSubgraph {\n private logger = new ConsoleLogger([\"PackagesSubgraph\"]);\n private packageManagementService: PackageManagementService;\n\n constructor(args: PackagesSubgraphArgs) {\n super(args);\n this.packageManagementService = args.packageManagementService;\n this.logger.verbose(`constructor()`);\n }\n\n name = \"packages\";\n hasSubscriptions = false;\n\n typeDefs = gql(schemaSource);\n\n resolvers = {\n Query: {\n Packages: () => ({}),\n },\n PackagesQueries: {\n installedPackages: async () => {\n this.logger.debug(\"installedPackages\");\n try {\n return await resolvers.installedPackages(\n this.packageManagementService,\n );\n } catch (error) {\n this.logger.error(\"Error in installedPackages: @error\", error);\n throw error;\n }\n },\n\n installedPackage: async (_parent: unknown, args: { name: string }) => {\n this.logger.debug(\"installedPackage(@args)\", args);\n try {\n return await resolvers.installedPackage(\n this.packageManagementService,\n args,\n );\n } catch (error) {\n this.logger.error(\"Error in installedPackage: @error\", error);\n throw error;\n }\n },\n },\n\n Mutation: {\n Packages: () => ({}),\n },\n\n PackagesMutations: {\n installPackage: async (\n _parent: unknown,\n args: { name: string; registryUrl?: string | null },\n ctx: Context,\n ) => {\n this.logger.debug(\"installPackage(@args)\", args);\n try {\n return await resolvers.installPackage(\n this.packageManagementService,\n this.authorizationService,\n args,\n ctx,\n );\n } catch (error) {\n this.logger.error(\"Error in installPackage: @error\", error);\n throw error;\n }\n },\n\n uninstallPackage: async (\n _parent: unknown,\n args: { name: string },\n ctx: Context,\n ) => {\n this.logger.debug(\"uninstallPackage(@args)\", args);\n try {\n return await resolvers.uninstallPackage(\n this.packageManagementService,\n this.authorizationService,\n args,\n ctx,\n );\n } catch (error) {\n this.logger.error(\"Error in uninstallPackage: @error\", error);\n throw error;\n }\n },\n },\n };\n\n onSetup(): Promise<void> {\n this.logger.debug(\"Setting up PackagesSubgraph\");\n return Promise.resolve();\n }\n}\n","import lzString from \"lz-string\";\n\n/**\n * The lz-compressed `explorerURLState` parameter carried by switchboard\n * explorer URLs: the JSON payload produced by\n * `buildDocumentSubgraphQuery` in `@powerhousedao/reactor-browser`,\n * `{ document, variables, headers? }` with `variables` and `headers`\n * already JSON-stringified.\n */\nexport interface ExplorerUrlState {\n /** The GraphQL query to prefill in GraphiQL. */\n query: string;\n /** JSON-stringified variables, as stored in the payload. */\n variables?: string;\n /** Request headers for the GraphiQL fetcher (e.g. Authorization). */\n headers?: Record<string, string>;\n}\n\n/**\n * Decodes an `explorerURLState` URL parameter. Returns `null` for anything\n * that is not a valid lz-compressed payload with a non-empty `document`.\n */\nexport function decodeExplorerUrlState(\n encoded: string,\n): ExplorerUrlState | null {\n try {\n const decompressed = lzString.decompressFromEncodedURIComponent(encoded);\n if (!decompressed) {\n return null;\n }\n const payload = JSON.parse(decompressed) as Record<string, unknown>;\n if (typeof payload.document !== \"string\" || payload.document.length === 0) {\n return null;\n }\n const variables =\n typeof payload.variables === \"string\" ? payload.variables : undefined;\n let headers: Record<string, string> | undefined;\n if (typeof payload.headers === \"string\") {\n const parsed: unknown = JSON.parse(payload.headers);\n if (parsed && typeof parsed === \"object\") {\n headers = parsed as Record<string, string>;\n }\n }\n return { query: payload.document, variables, headers };\n } catch {\n return null;\n }\n}\n\n/**\n * Pinned CDN versions for GraphiQL playground dependencies.\n * Using pinned versions avoids unpkg.com redirect issues that can\n * trigger CORS errors in the browser.\n */\nconst CDN_VERSIONS = {\n react: \"18.3.1\",\n reactDom: \"18.3.1\",\n graphiql: \"3.8.3\",\n pluginExplorer: \"4.0.0\",\n};\n\n/**\n * Escape a string for embedding as a single-quoted JS string literal inside\n * an HTML `<script>` block. The payload reaches the browser through an\n * attacker-controllable URL parameter, so the embedding must survive two\n * parsers: HTML (a `</script>` inside the string would end the script\n * element and start a new, attacker-authored one) and JS (backticks,\n * `${...}` and quotes in the content would otherwise break out of the\n * literal). Backslash, quote, CR and LF escapes keep the literal valid;\n * every `<` becomes `\\u003c`, which no HTML parser reads as a tag opener.\n * The escapes resolve when the script parses, so the in-memory value is\n * byte-identical to the input.\n */\nfunction jsStringEscape(value: string): string {\n return value\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/'/g, \"\\\\'\")\n .replace(/\\r/g, \"\\\\r\")\n .replace(/\\n/g, \"\\\\n\")\n .replace(/</g, \"\\\\u003c\");\n}\n\n/**\n * JSON is already a valid JS object/string literal; the only HTML-hostile\n * byte left is `<` (e.g. `</script>` inside a string value).\n */\nfunction jsJsonEscape(json: string): string {\n return json.replace(/</g, \"\\\\u003c\");\n}\n\nexport function renderGraphqlPlayground(\n url: string,\n query?: string,\n headers: Record<string, string> = {},\n variables?: string,\n): string {\n return `<!doctype html>\n <html lang=\"en\">\n <head>\n <title>GraphiQL</title>\n <style>\n body {\n height: 100%;\n margin: 0;\n width: 100%;\n overflow: hidden;\n }\n\n #graphiql {\n height: 100vh;\n }\n </style>\n <script\n src=\"https://unpkg.com/react@${CDN_VERSIONS.react}/umd/react.production.min.js\"\n ></script>\n <script\n src=\"https://unpkg.com/react-dom@${CDN_VERSIONS.reactDom}/umd/react-dom.production.min.js\"\n ></script>\n <script\n src=\"https://unpkg.com/graphiql@${CDN_VERSIONS.graphiql}/graphiql.min.js\"\n ></script>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/graphiql@${CDN_VERSIONS.graphiql}/graphiql.min.css\" />\n <script\n src=\"https://unpkg.com/@graphiql/plugin-explorer@${CDN_VERSIONS.pluginExplorer}/dist/index.umd.js\"\n ></script>\n <link\n rel=\"stylesheet\"\n href=\"https://unpkg.com/@graphiql/plugin-explorer@${CDN_VERSIONS.pluginExplorer}/dist/style.css\"\n />\n </head>\n\n <body>\n <div id=\"graphiql\">Loading...</div>\n <script>\n var fetcher = GraphiQL.createFetcher({\n url: '${jsStringEscape(url)}',\n headers: ${jsJsonEscape(JSON.stringify(headers))}\n });\n var defaultQuery = ${\n query ? `'${jsStringEscape(query)}'` : \"undefined\"\n };\n var defaultVariables = ${\n variables ? `'${jsStringEscape(variables)}'` : \"undefined\"\n };\n\n // GraphiQL only applies defaultQuery/variables when the editor has\n // no persisted value. Overwrite any stale persisted state so a\n // returning user still gets the document-scoped query/variables\n // instead of their last session's.\n if (defaultQuery && localStorage.getItem(\"graphiql:query\")) {\n localStorage.setItem(\"graphiql:query\", defaultQuery);\n }\n if (defaultVariables && localStorage.getItem(\"graphiql:variables\")) {\n localStorage.setItem(\"graphiql:variables\", defaultVariables);\n }\n\n var explorerPlugin = GraphiQLPluginExplorer.explorerPlugin();\n\n function GraphiQLWithExplorer() {\n return React.createElement(GraphiQL, {\n fetcher: fetcher,\n defaultEditorToolsVisibility: true,\n plugins: [explorerPlugin],\n defaultQuery: defaultQuery,\n variables: defaultVariables\n });\n }\n\n const root = ReactDOM.createRoot(document.getElementById('graphiql'));\n root.render(React.createElement(GraphiQLWithExplorer));\n </script>\n </body>\n </html>`;\n}\n","import type { DocumentNode } from \"graphql\";\nimport { print } from \"graphql\";\nimport type { Requester } from \"./gen/graphql.js\";\n\nexport type FetchLike = (\n input: URL | string,\n init: RequestInit,\n) => Promise<Response>;\n\ninterface GraphQLResponse<T = unknown> {\n data?: T;\n errors?: Array<{ message: string; locations?: unknown; path?: unknown }>;\n}\n\nexport function createFetchRequester(\n url: string,\n fetchImpl: FetchLike,\n baseHeaders: Record<string, string> = {},\n): Requester {\n return async <R, V>(document: DocumentNode, variables?: V) => {\n const res = await fetchImpl(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n ...baseHeaders,\n },\n body: JSON.stringify({ query: print(document), variables }),\n });\n\n if (!res.ok) {\n throw new Error(`GraphQL HTTP ${res.status}`);\n }\n\n const json = (await res.json()) as GraphQLResponse<R>;\n if (json.errors) {\n throw new Error(JSON.stringify(json.errors));\n }\n\n return json.data as R;\n };\n}\n","import { z } from \"zod\";\n\n// Scalar DTOs\nexport const JSONObjectDTO = z.unknown();\nexport const DateTimeDTO = z.union([z.string(), z.date()]);\n\nexport const DocumentModelStateDTO = z\n .object({\n id: z.string(),\n name: z.string(),\n namespace: z.string().nullable().optional(),\n version: z.string().nullable().optional(),\n specification: JSONObjectDTO.nullable().optional(),\n })\n .strip();\n\nexport const DocumentModelResultPageDTO = z\n .object({\n items: z.array(DocumentModelStateDTO),\n hasNextPage: z.boolean(),\n hasPreviousPage: z.boolean(),\n cursor: z.string().nullable().optional(),\n })\n .strip();\n\nexport const RevisionEntryDTO = z\n .object({\n scope: z.string(),\n revision: z.number().int(),\n })\n .strip();\n\nexport const PHDocumentDTO = z\n .object({\n id: z.string(),\n slug: z.string().nullable().optional(),\n name: z.string(),\n documentType: z.string(),\n state: JSONObjectDTO,\n revisionsList: z.array(RevisionEntryDTO),\n createdAtUtcIso: DateTimeDTO,\n lastModifiedAtUtcIso: DateTimeDTO,\n })\n .strip();\n\nexport const PHDocumentResultPageDTO = z\n .object({\n items: z.array(PHDocumentDTO),\n hasNextPage: z.boolean(),\n hasPreviousPage: z.boolean(),\n cursor: z.string().nullable().optional(),\n })\n .strip();\n\nexport const DocumentRelationshipDTO = z\n .object({\n sourceId: z.string(),\n targetId: z.string(),\n relationshipType: z.string(),\n metadata: JSONObjectDTO.nullable().optional(),\n createdAt: DateTimeDTO,\n updatedAt: DateTimeDTO,\n })\n .strip();\n\nexport const DocumentRelationshipResultPageDTO = z\n .object({\n items: z.array(DocumentRelationshipDTO),\n hasNextPage: z.boolean(),\n hasPreviousPage: z.boolean(),\n cursor: z.string().nullable().optional(),\n })\n .strip();\n\nexport const DocumentWithChildrenDTO = z\n .object({\n document: PHDocumentDTO,\n childIds: z.array(z.string()),\n })\n .strip();\n\nexport const MoveRelationshipResultDTO = z\n .object({\n source: PHDocumentDTO,\n target: PHDocumentDTO,\n })\n .strip();\n\nexport const JobInfoDTO = z\n .object({\n id: z.string(),\n status: z.string(),\n result: JSONObjectDTO.nullable().optional(),\n error: z.string().nullable().optional(),\n createdAt: DateTimeDTO,\n completedAt: DateTimeDTO.nullable().optional(),\n })\n .strip();\n\n// Operation DTOs for GetDocumentOperations\nexport const ActionSignerUserDTO = z\n .object({\n address: z.string(),\n networkId: z.string(),\n chainId: z.number().int(),\n })\n .strip();\n\nexport const ActionSignerAppDTO = z\n .object({\n name: z.string(),\n key: z.string(),\n })\n .strip();\n\nexport const ActionSignerDTO = z\n .object({\n signatures: z.array(z.string()),\n user: ActionSignerUserDTO.nullable().optional(),\n app: ActionSignerAppDTO.nullable().optional(),\n })\n .strip();\n\nexport const ActionContextDTO = z\n .object({\n signer: ActionSignerDTO.nullable().optional(),\n })\n .strip();\n\nexport const OperationActionDTO = z\n .object({\n id: z.string(),\n type: z.string(),\n timestampUtcMs: z.string(),\n input: z.unknown(),\n scope: z.string(),\n context: ActionContextDTO.nullable().optional(),\n })\n .strip();\n\nexport const OperationDTO = z\n .object({\n index: z.number().int(),\n timestampUtcMs: z.string(),\n hash: z.string(),\n skip: z.number().int(),\n error: z.string().nullable().optional(),\n id: z.string().nullable().optional(),\n action: OperationActionDTO,\n })\n .strip();\n\nexport const OperationResultPageDTO = z\n .object({\n items: z.array(OperationDTO),\n hasNextPage: z.boolean(),\n hasPreviousPage: z.boolean(),\n cursor: z.string().nullable().optional(),\n })\n .strip();\n\nexport const DocumentWithChildrenAndOperationsDTO = z\n .object({\n document: PHDocumentDTO.extend({\n operations: OperationResultPageDTO.optional(),\n }),\n childIds: z.array(z.string()),\n })\n .strip();\n\nexport const DocumentChangeContextDTO = z\n .object({\n parentId: z.string().nullable().optional(),\n childId: z.string().nullable().optional(),\n })\n .strip();\n\nexport const DocumentChangeEventDTO = z\n .object({\n type: z.string(),\n documents: z.array(PHDocumentDTO),\n context: DocumentChangeContextDTO.nullable().optional(),\n })\n .strip();\n\nexport const ActionEvaluationDTO = z\n .object({\n decision: z.enum([\"ALLOW\", \"DENY\"]),\n reason: z.string().nullable().optional(),\n })\n .strip();\n\nexport const ActionEvaluationsDTO = z\n .object({\n evaluations: z.array(ActionEvaluationDTO),\n allAllowed: z.boolean(),\n anyAllowed: z.boolean(),\n allDenied: z.boolean(),\n anyDenied: z.boolean(),\n })\n .strip();\n\nexport const JobChangeEventDTO = z\n .object({\n jobId: z.string(),\n status: z.string(),\n result: JSONObjectDTO.nullable().optional(),\n error: z.string().nullable().optional(),\n })\n .strip();\n","import type { DocumentNode, OperationDefinitionNode } from \"graphql\";\nimport { Kind } from \"graphql\";\nimport type {\n DocumentModelResultPage,\n JobInfo,\n PhDocumentResultPage,\n Requester,\n Sdk,\n} from \"./gen/graphql.js\";\nimport type { FetchLike } from \"./requester.js\";\nimport { createFetchRequester } from \"./requester.js\";\nimport {\n ActionEvaluationsDTO,\n DocumentChangeEventDTO,\n DocumentModelResultPageDTO,\n DocumentRelationshipResultPageDTO,\n DocumentWithChildrenAndOperationsDTO,\n DocumentWithChildrenDTO,\n JobChangeEventDTO,\n JobInfoDTO,\n MoveRelationshipResultDTO,\n OperationResultPageDTO,\n PHDocumentDTO,\n PHDocumentResultPageDTO,\n} from \"./validation.js\";\n\ntype OperationName = keyof Sdk;\ntype OperationHandler = (data: Record<string, unknown>) => void;\n\n// This type enforces that ALL operations from Sdk must have a handler\n// TypeScript will error if any operation is missing\ntype OperationValidators = { [K in OperationName]: OperationHandler };\n\n// Validation handlers for each operation\n// TypeScript will error if any operation from Sdk is missing\nconst operationValidators: OperationValidators = {\n GetDocument: (data) => {\n if (data.document) {\n DocumentWithChildrenDTO.parse(data.document);\n }\n },\n GetDocumentWithOperations: (data) => {\n if (data.document) {\n DocumentWithChildrenAndOperationsDTO.parse(data.document);\n }\n },\n GetDocumentModels: (data) => {\n if (data.documentModels) {\n DocumentModelResultPageDTO.parse(\n data.documentModels as DocumentModelResultPage,\n );\n }\n },\n GetDocumentOutgoingRelationships: (data) => {\n if (data.documentOutgoingRelationships) {\n PHDocumentResultPageDTO.parse(\n data.documentOutgoingRelationships as PhDocumentResultPage,\n );\n }\n },\n GetDocumentIncomingRelationships: (data) => {\n if (data.documentIncomingRelationships) {\n PHDocumentResultPageDTO.parse(\n data.documentIncomingRelationships as PhDocumentResultPage,\n );\n }\n },\n GetDocumentOutgoingRelationshipEdges: (data) => {\n if (data.documentOutgoingRelationshipEdges) {\n DocumentRelationshipResultPageDTO.parse(\n data.documentOutgoingRelationshipEdges,\n );\n }\n },\n GetDocumentIncomingRelationshipEdges: (data) => {\n if (data.documentIncomingRelationshipEdges) {\n DocumentRelationshipResultPageDTO.parse(\n data.documentIncomingRelationshipEdges,\n );\n }\n },\n FindDocuments: (data) => {\n if (data.findDocuments) {\n PHDocumentResultPageDTO.parse(data.findDocuments as PhDocumentResultPage);\n }\n },\n GetDocumentOperations: (data) => {\n if (data.documentOperations) {\n OperationResultPageDTO.parse(data.documentOperations);\n }\n },\n GetJobStatus: (data) => {\n if (data.jobStatus) {\n JobInfoDTO.parse(data.jobStatus as JobInfo);\n }\n },\n EvaluateActions: (data) => {\n if (data.evaluateActions) {\n ActionEvaluationsDTO.parse(data.evaluateActions);\n }\n },\n // Mutations\n CreateDocument: (data) => {\n if (data.createDocument) {\n PHDocumentDTO.parse(data.createDocument);\n }\n },\n CreateEmptyDocument: (data) => {\n if (data.createEmptyDocument) {\n PHDocumentDTO.parse(data.createEmptyDocument);\n }\n },\n MutateDocument: (data) => {\n if (data.mutateDocument) {\n PHDocumentDTO.parse(data.mutateDocument);\n }\n },\n MutateDocumentAsync: (data) => {\n if (data.mutateDocumentAsync) {\n // Returns a job ID string\n }\n },\n RenameDocument: (data) => {\n if (data.renameDocument) {\n PHDocumentDTO.parse(data.renameDocument);\n }\n },\n SetPreferredEditor: (data) => {\n if (data.setPreferredEditor) {\n PHDocumentDTO.parse(data.setPreferredEditor);\n }\n },\n AddRelationship: (data) => {\n if (data.addRelationship) {\n PHDocumentDTO.parse(data.addRelationship);\n }\n },\n UpdateRelationship: (data) => {\n if (data.updateRelationship) {\n PHDocumentDTO.parse(data.updateRelationship);\n }\n },\n RemoveRelationship: (data) => {\n if (data.removeRelationship) {\n PHDocumentDTO.parse(data.removeRelationship);\n }\n },\n MoveRelationship: (data) => {\n if (data.moveRelationship) {\n MoveRelationshipResultDTO.parse(data.moveRelationship);\n }\n },\n DeleteDocument: (data) => {\n if (data.deleteDocument !== undefined) {\n // Returns a boolean\n }\n },\n DeleteDocuments: (data) => {\n if (data.deleteDocuments !== undefined) {\n // Returns a boolean\n }\n },\n // Subscriptions\n DocumentChanges: (data) => {\n if (data.documentChanges) {\n DocumentChangeEventDTO.parse(data.documentChanges);\n }\n },\n JobChanges: (data) => {\n if (data.jobChanges) {\n JobChangeEventDTO.parse(data.jobChanges);\n }\n },\n // Sync operations (used inline by reactor/gql-req-channel.ts, not through this SDK)\n PollSyncEnvelopes: () => {},\n TouchChannel: () => {},\n PushSyncEnvelopes: () => {},\n};\n\nexport function createValidatingRequester(\n url: string,\n fetchImpl: FetchLike,\n headers?: Record<string, string>,\n): Requester {\n const base = createFetchRequester(url, fetchImpl, headers);\n return async <R, V>(\n document: DocumentNode,\n variables?: V,\n options?: RequestInit,\n ): Promise<R> => {\n const data = (await base(document, variables, options)) as R;\n\n // Extract operation name from the document\n const operationDef = document.definitions.find(\n (d): d is OperationDefinitionNode =>\n d.kind === Kind.OPERATION_DEFINITION && !!d.name,\n );\n const operationName = operationDef?.name?.value;\n\n // Validate based on operation name\n if (data && operationName && operationName in operationValidators) {\n const validator = operationValidators[operationName as OperationName];\n validator(data as Record<string, unknown>);\n }\n\n return data;\n };\n}\n","import { getSdk } from \"./gen/graphql.js\";\nimport type { FetchLike } from \"./requester.js\";\nimport { createValidatingRequester } from \"./requester.with-zod.js\";\n\nexport function createReactorGraphQLClient(\n url: string,\n fetchImpl: FetchLike = fetch,\n headers?: Record<string, string>,\n) {\n const requester = createValidatingRequester(url, fetchImpl, headers);\n return getSdk(requester);\n}\n","\"# 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}\\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 TouchChannelInput {\\n id: String!\\n name: String!\\n collectionId: String!\\n filter: RemoteFilterInput!\\n sinceTimestampUtcMs: String!\\n}\\n\\ntype TouchChannelResult {\\n success: Boolean!\\n ackOrdinal: Int!\\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 ): PollSyncEnvelopesResult!\\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(envelopes: [SyncEnvelopeInput!]!): 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\"","import type {\n DocumentChangeEvent,\n IReactorClient,\n JobResultSummary,\n SearchFilter,\n ViewFilter,\n} from \"@powerhousedao/reactor\";\nimport type { AuthSubject } from \"@powerhousedao/shared/document-model\";\nimport { PubSub } from \"graphql-subscriptions\";\n\nconst pubSub = new PubSub();\n\nexport function getPubSub(): PubSub {\n return pubSub;\n}\n\nexport type SubscriptionTriggers = {\n DOCUMENT_CHANGES: string;\n JOB_CHANGES: string;\n};\n\nexport const SUBSCRIPTION_TRIGGERS: SubscriptionTriggers = {\n DOCUMENT_CHANGES: \"DOCUMENT_CHANGES\",\n JOB_CHANGES: \"JOB_CHANGES\",\n};\n\nexport interface DocumentChangesPayload {\n documentChanges: DocumentChangeEvent;\n search: SearchFilter;\n view?: ViewFilter;\n}\n\nexport interface JobChangesPayload {\n jobChanges: {\n jobId: string;\n status: string;\n createdAt: string;\n completedAt: string | null;\n error: string | null;\n result: JobResultSummary | null;\n };\n jobId: string;\n /** Document id used to authorize the subscription; not in the GraphQL event. */\n documentId: string;\n}\n\ntype Feed = { unsubscribe: () => void; subscribers: number };\n\n// Anonymous callers share one feed; `|` cannot occur in an address or a did:key.\nfunction subjectKey(subject: AuthSubject): string {\n return `${subject.address ?? \"\"}|${subject.key ?? \"\"}`;\n}\n\n/**\n * The reactor's change feed, read once per distinct subject and shared by that\n * subject's GraphQL subscriptions. Each feed is read as its subject, so the\n * client withholds what that subject may not read; one feed read with no view\n * would gate every subscriber as the host.\n */\nexport class DocumentChangeFeed {\n readonly #pubSub = new PubSub();\n readonly #feeds = new Map<string, Feed>();\n\n constructor(private readonly reactorClient: IReactorClient) {}\n\n subscribe(\n subject: AuthSubject,\n ): AsyncIterableIterator<DocumentChangesPayload> {\n const key = subjectKey(subject);\n const topic = `${SUBSCRIPTION_TRIGGERS.DOCUMENT_CHANGES}:${key}`;\n const iterator =\n this.#pubSub.asyncIterableIterator<DocumentChangesPayload>(topic);\n this.#acquire(key, topic, subject);\n\n let released = false;\n const release = () => {\n if (!released) {\n released = true;\n this.#release(key);\n }\n };\n\n return {\n next: () => iterator.next(),\n return: () => {\n release();\n return iterator.return();\n },\n throw: (error: unknown) => {\n release();\n return iterator.throw(error);\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n }\n\n #acquire(key: string, topic: string, subject: AuthSubject): void {\n const feed = this.#feeds.get(key);\n if (feed) {\n feed.subscribers++;\n return;\n }\n\n const view: ViewFilter = { subject };\n const unsubscribe = this.reactorClient.subscribe(\n {},\n (event: DocumentChangeEvent) => {\n const payload: DocumentChangesPayload = {\n documentChanges: event,\n search: {},\n view,\n };\n void this.#pubSub.publish(topic, payload);\n },\n view,\n );\n this.#feeds.set(key, { unsubscribe, subscribers: 1 });\n }\n\n #release(key: string): void {\n const feed = this.#feeds.get(key);\n if (!feed) {\n return;\n }\n feed.subscribers--;\n if (feed.subscribers === 0) {\n this.#feeds.delete(key);\n feed.unsubscribe();\n }\n }\n}\n\nconst activeJobSubscriptions = new Map<\n string,\n {\n cancel: () => void;\n refCount: number;\n }\n>();\n\nexport function ensureJobSubscription(\n reactorClient: IReactorClient,\n jobId: string,\n): () => void {\n let subscription = activeJobSubscriptions.get(jobId);\n\n if (!subscription) {\n let isCancelled = false;\n let timeoutId: NodeJS.Timeout | undefined;\n\n const poll = async () => {\n if (isCancelled) {\n return;\n }\n\n const jobInfo = await reactorClient.getJobStatus(jobId);\n const payload: JobChangesPayload = {\n jobChanges: {\n jobId: jobInfo.id,\n status: jobInfo.status,\n createdAt: jobInfo.createdAtUtcIso,\n completedAt: jobInfo.completedAtUtcIso ?? null,\n error: jobInfo.error?.message ?? null,\n result: jobInfo.result ?? null,\n },\n jobId,\n documentId: jobInfo.documentId,\n };\n\n void pubSub.publish(SUBSCRIPTION_TRIGGERS.JOB_CHANGES, payload);\n\n const isTerminal =\n String(jobInfo.status) === \"FAILED\" ||\n String(jobInfo.status) === \"READ_MODELS_READY\" ||\n jobInfo.completedAtUtcIso !== undefined;\n\n if (!isTerminal && !isCancelled) {\n timeoutId = setTimeout(() => {\n void poll().catch((error) => {\n console.error(\"Error polling job status:\", error);\n });\n }, 1000);\n } else if (isTerminal) {\n activeJobSubscriptions.delete(jobId);\n }\n };\n\n void poll().catch((error) => {\n console.error(\"Error starting job polling:\", error);\n });\n\n const cancel = () => {\n isCancelled = true;\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n };\n\n subscription = { cancel, refCount: 0 };\n activeJobSubscriptions.set(jobId, subscription);\n }\n\n subscription.refCount++;\n\n return () => {\n if (subscription) {\n subscription.refCount--;\n if (subscription.refCount === 0) {\n subscription.cancel();\n activeJobSubscriptions.delete(jobId);\n }\n }\n };\n}\n","import { ConsoleLogger } from \"document-model\";\nimport { DriveCollectionId } from \"@powerhousedao/reactor\";\nimport { GraphQLError } from \"graphql\";\nimport { ForbiddenError } from \"../errors.js\";\nimport { withFilter } from \"graphql-subscriptions\";\nimport { gql } from \"graphql-tag\";\nimport schemaSource from \"./schema.graphql\";\nimport {\n AuthorizedDocumentHandle,\n type CanonicalDocumentId,\n} from \"../../services/authorization.service.js\";\nimport { BaseSubgraph } from \"../base-subgraph.js\";\nimport type { Context, SubgraphArgs } from \"../types.js\";\nimport {\n collectChangedDocumentIds,\n matchesJobFilter,\n matchesSearchFilter,\n toGqlDocumentChangeEvent,\n} from \"./adapters.js\";\nimport { isDriveContainerType } from \"./constants.js\";\nimport type { Resolvers } from \"./gen/graphql.js\";\nimport {\n DocumentChangeFeed,\n ensureJobSubscription,\n getPubSub,\n SUBSCRIPTION_TRIGGERS,\n type DocumentChangesPayload,\n type JobChangesPayload,\n} from \"./pubsub.js\";\nimport * as resolvers from \"./resolvers.js\";\n\nexport class ReactorSubgraph extends BaseSubgraph {\n // temp\n private logger = new ConsoleLogger([\"ReactorSubgraph\"]);\n\n constructor(args: SubgraphArgs) {\n super(args);\n this.logger.verbose(`constructor()`);\n }\n\n name = \"r\";\n hasSubscriptions = true;\n\n #documentChanges: DocumentChangeFeed | undefined;\n\n private get documentChanges(): DocumentChangeFeed {\n this.#documentChanges ??= new DocumentChangeFeed(this.reactorClient);\n return this.#documentChanges;\n }\n\n /**\n * Check operation-level permissions for an array of actions.\n * Delegates to base assertCanExecuteOperation for each action.\n */\n private async assertCanExecuteOperations(\n documentId: string,\n actions: readonly unknown[],\n ctx: Context,\n ): Promise<AuthorizedDocumentHandle> {\n let handle = AuthorizedDocumentHandle.skipped(documentId);\n for (const action of actions) {\n if (!action || typeof action !== \"object\") continue;\n const actionObj = action as Record<string, unknown>;\n const operationType = actionObj.type;\n if (typeof operationType !== \"string\") continue;\n\n handle = await this.assertCanExecuteOperation(\n documentId,\n operationType,\n ctx,\n );\n }\n return handle;\n }\n\n /**\n * Returns the drive id when the given identifier (id or slug) refers\n * to a drive document, otherwise undefined. Used by deleteDocument to\n * decide whether to invalidate the drive-ownership cache after a\n * successful delete.\n */\n async #resolveDriveId(identifier: string): Promise<string | undefined> {\n try {\n const doc = await this.reactorClient.get(identifier);\n if (isDriveContainerType(doc.header.documentType)) {\n return doc.header.id;\n }\n return undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Drops the relationship edges whose far-end document the caller cannot read.\n *\n * An edge names two documents, so returning it discloses the far end's id. The\n * document-shaped relationship queries already withhold far-end documents the\n * caller cannot read; the edge-shaped queries have to withhold the same ones,\n * or they become a way to enumerate around that check. Supreme admins read\n * everything, so the per-edge check is skipped for them.\n *\n * The cursor describes where to resume in the underlying unfiltered stream,\n * so it is left as it came. A filtered page is therefore often shorter than\n * the requested limit, and that is the stream continuing rather than a sign\n * it ended.\n */\n private async filterRelationshipEdges<\n TEdge extends { readonly sourceId: string; readonly targetId: string },\n TPage extends { readonly items: ReadonlyArray<TEdge> },\n >(\n page: TPage,\n farEnd: \"sourceId\" | \"targetId\",\n ctx: Context,\n ): Promise<TPage> {\n if (this.authorizationService.isSupremeAdmin(ctx.user?.address)) {\n return page;\n }\n\n const decisions = new Map<string, boolean>();\n const items: TEdge[] = [];\n for (const edge of page.items) {\n const documentId = edge[farEnd];\n let canRead = decisions.get(documentId);\n if (canRead === undefined) {\n canRead = await this.canReadDocument(\n documentId as CanonicalDocumentId,\n ctx,\n );\n decisions.set(documentId, canRead);\n }\n if (canRead) {\n items.push(edge);\n }\n }\n\n return { ...page, items };\n }\n\n /**\n * Adds to `forbidden` the canonical document ids in `syncOps` that the caller\n * cannot read, checking each distinct id once. Sync operation document ids are\n * canonical (never slugs), so no resolution is needed.\n */\n async #collectForbiddenDocuments(\n syncOps: ReadonlyArray<{ documentId: string }>,\n forbidden: Set<string>,\n ctx: Context,\n ): Promise<void> {\n const checked = new Set<string>();\n for (const syncOp of syncOps) {\n const documentId = syncOp.documentId;\n if (checked.has(documentId) || forbidden.has(documentId)) continue;\n checked.add(documentId);\n const canRead = await this.canReadDocument(\n documentId as CanonicalDocumentId,\n ctx,\n );\n if (!canRead) forbidden.add(documentId);\n }\n }\n\n /**\n * Enforces which subject a sync channel answers to, adopting an unclaimed one.\n *\n * A channel is a private queue: it names a collection, and it accumulates\n * exactly the operations one subject is owed, so serving it to a second\n * subject would hand over that subject's cursor as well as its contents. An\n * unbound channel -- created anonymously, or created before binding existed --\n * is claimed by the first authenticated subject to use it, and answers to that\n * address alone thereafter. Adoption is safe precisely because serving\n * withholds rather than consumes: before it was claimed the channel served\n * only what an anonymous subject may read, and everything withheld is still\n * queued for the adopter.\n *\n * The refusal is the shape a read denial takes, so a puller treats it as a\n * signal to authenticate again rather than as a transport failure. Pushes are\n * refused the same way -- a push interacts with the same private queue, and\n * reports the liveness that keeps it from being reclaimed -- but they never\n * adopt, since the push path has no drive check to clear the claimant.\n *\n * Nothing is enforced or adopted without a serving gate: with no gate the\n * channel serves every subject alike, so there is no subject for it to\n * belong to.\n */\n async #bindOrRefuseChannel(\n channelId: string,\n ctx: Context,\n options: { adopt?: boolean; action?: \"poll\" | \"push to\" } = {},\n ): Promise<void> {\n if (!this.syncServingGate) return;\n\n // Claiming a channel is a write, so only a caller the coarse drive check\n // has already cleared may do it. The push path has no such check and asks\n // for refusal alone, or any authenticated address could claim a channel it\n // can never poll and lock its rightful owner out for good.\n const { adopt = true, action = \"poll\" } = options;\n\n let remote;\n try {\n remote = this.syncManager.getById(channelId);\n } catch {\n // Not registered yet: touchChannel is about to create it, bound to its\n // creator.\n return;\n }\n\n const bound = remote.meta.options.boundAddress;\n const address = ctx.user?.address;\n\n if (bound === undefined) {\n if (adopt && address !== undefined) {\n await this.syncManager.bindRemote(channelId, address);\n }\n return;\n }\n\n if (bound !== address) {\n throw new ForbiddenError(`to ${action} this sync channel`);\n }\n }\n\n /** The address a channel created by this request belongs to, if any. */\n #creatorBinding(ctx: Context): string | undefined {\n return this.syncServingGate ? ctx.user?.address : undefined;\n }\n\n typeDefs = gql(schemaSource);\n\n resolvers: Resolvers = {\n // Field resolver for PHDocument.operations - fetches operations on demand\n PHDocument: {\n operations: async (parent, args, ctx: Context) => {\n this.logger.debug(\n \"PHDocument.operations(@parent.id, @args)\",\n parent.id,\n args,\n );\n\n await this.assertCanReadCanonical(\n parent.id as CanonicalDocumentId,\n ctx,\n );\n\n try {\n // Build the filter using the document's id\n const filter = {\n documentId: parent.id,\n branch: args.filter?.branch,\n scopes: args.filter?.scopes,\n actionTypes: args.filter?.actionTypes,\n sinceRevision: args.filter?.sinceRevision,\n timestampFrom: args.filter?.timestampFrom,\n timestampTo: args.filter?.timestampTo,\n };\n\n return await resolvers.documentOperations(\n this.reactorClient,\n { filter, paging: args.paging },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\"Error in PHDocument.operations: @Error\", error);\n throw error;\n }\n },\n },\n\n Query: {\n documentModels: async (_parent, args) => {\n this.logger.debug(\"documentModels(@args)\", args);\n try {\n return await resolvers.documentModels(this.reactorClient, args);\n } catch (error) {\n this.logger.error(\"Error in documentModels: @Error\", error);\n throw error;\n }\n },\n\n document: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"document(@args)\", args);\n try {\n const handle = await this.assertCanRead(args.identifier, ctx);\n return await resolvers.document(\n this.reactorClient,\n { ...args, identifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\"Error in document: @Error\", error);\n throw error;\n }\n },\n\n documentOutgoingRelationships: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"documentOutgoingRelationships(@args)\", args);\n try {\n const handle = await this.assertCanRead(args.sourceIdentifier, ctx);\n return await resolvers.documentOutgoingRelationships(\n this.reactorClient,\n { ...args, sourceIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in documentOutgoingRelationships: @Error\",\n error,\n );\n throw error;\n }\n },\n\n documentIncomingRelationships: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"documentIncomingRelationships(@args)\", args);\n try {\n const handle = await this.assertCanRead(args.targetIdentifier, ctx);\n const result = await resolvers.documentIncomingRelationships(\n this.reactorClient,\n { ...args, targetIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n if (!this.authorizationService.isSupremeAdmin(ctx.user?.address)) {\n const filteredItems = [];\n for (const item of result.items) {\n const canRead = await this.canReadDocument(\n item.id as CanonicalDocumentId,\n ctx,\n );\n if (canRead) {\n filteredItems.push(item);\n }\n }\n return { ...result, items: filteredItems };\n }\n\n return result;\n } catch (error) {\n this.logger.error(\n \"Error in documentIncomingRelationships: @Error\",\n error,\n );\n throw error;\n }\n },\n\n documentOutgoingRelationshipEdges: async (\n _parent,\n args,\n ctx: Context,\n ) => {\n this.logger.debug(\"documentOutgoingRelationshipEdges(@args)\", args);\n try {\n const handle = await this.assertCanRead(args.sourceIdentifier, ctx);\n const result = await resolvers.documentOutgoingRelationshipEdges(\n this.reactorClient,\n { ...args, sourceIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n return await this.filterRelationshipEdges(result, \"targetId\", ctx);\n } catch (error) {\n this.logger.error(\n \"Error in documentOutgoingRelationshipEdges: @Error\",\n error,\n );\n throw error;\n }\n },\n\n documentIncomingRelationshipEdges: async (\n _parent,\n args,\n ctx: Context,\n ) => {\n this.logger.debug(\"documentIncomingRelationshipEdges(@args)\", args);\n try {\n const handle = await this.assertCanRead(args.targetIdentifier, ctx);\n const result = await resolvers.documentIncomingRelationshipEdges(\n this.reactorClient,\n { ...args, targetIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n return await this.filterRelationshipEdges(result, \"sourceId\", ctx);\n } catch (error) {\n this.logger.error(\n \"Error in documentIncomingRelationshipEdges: @Error\",\n error,\n );\n throw error;\n }\n },\n\n findDocuments: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"findDocuments(@args)\", args);\n try {\n const result = await resolvers.findDocuments(\n this.reactorClient,\n { ...args, search: args.search ?? {} },\n this.viewSubject(ctx),\n );\n\n // Filter results to only include documents the user can read\n if (!this.authorizationService.isSupremeAdmin(ctx.user?.address)) {\n const filteredItems = [];\n for (const item of result.items) {\n const canRead = await this.canReadDocument(\n item.id as CanonicalDocumentId,\n ctx,\n );\n if (canRead) {\n filteredItems.push(item);\n }\n }\n return { ...result, items: filteredItems };\n }\n\n return result;\n } catch (error) {\n this.logger.error(\"Error in findDocuments: @Error\", error);\n throw error;\n }\n },\n\n jobStatus: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"jobStatus(@args)\", args);\n try {\n return await resolvers.jobStatus(this.reactorClient, args, (id) =>\n this.servesDocument(id, ctx),\n );\n } catch (error) {\n this.logger.error(\"Error in jobStatus: @Error\", error);\n throw error;\n }\n },\n\n documentOperations: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"documentOperations(@args)\", args);\n try {\n const handle = await this.assertCanRead(args.filter.documentId, ctx);\n return await resolvers.documentOperations(\n this.reactorClient,\n {\n ...args,\n filter: {\n ...args.filter,\n documentId: handle.fetchIdentifier,\n },\n },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\"Error in documentOperations: @Error\", error);\n throw error;\n }\n },\n\n /**\n * Gated on reading the document, the same gate every other read here\n * carries: a verdict is derived from the document's policy, so a caller\n * who may not read the document may not preflight against it either.\n * That gate decides whether the query runs; the answer comes entirely\n * from the reactor's decision model.\n */\n evaluateActions: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"evaluateActions(@args)\", args);\n try {\n const handle = await this.assertCanRead(args.documentIdentifier, ctx);\n return await resolvers.evaluateActions(\n this.reactorClient,\n { ...args, documentIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\"Error in evaluateActions: @Error\", error);\n throw error;\n }\n },\n\n pollSyncEnvelopes: async (\n _parent: unknown,\n args: { channelId: string; outboxAck: number; outboxLatest: number },\n ctx: Context,\n ) => {\n this.logger.debug(\"pollSyncEnvelopes(@args)\", args);\n\n try {\n let remote;\n try {\n remote = this.syncManager.getById(args.channelId);\n } catch (error) {\n throw new GraphQLError(\n `Channel not found: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // A collection is a drive-level abstraction; its canonical drive id is\n // carried by the collection id (never a slug).\n const driveId = remote.meta.collectionId\n .driveId as CanonicalDocumentId;\n const isAdmin = this.authorizationService.isSupremeAdmin(\n ctx.user?.address,\n );\n\n // Tier 1: reading any operation in a collection requires read access to\n // the drive it belongs to. No drive read, no document read.\n if (!isAdmin) {\n await this.assertCanReadCanonical(driveId, ctx);\n }\n\n // Adoption is a write, so it comes after the drive check: a caller\n // this collection refuses must not claim the channel on its way out.\n // `bindRemote` will not rebind, so a stray claim would lock the\n // rightful owner out for good. touchChannel orders these the same way.\n await this.#bindOrRefuseChannel(args.channelId, ctx);\n\n // Tier 2/3: drop operations and dead letters for documents the caller\n // cannot read individually.\n const forbiddenIds = new Set<string>();\n if (!isAdmin) {\n // A caller who can read a *protected* drive holds a grant that\n // inherits to every in-collection member, so the outbox needs no\n // per-document check. Only a world-readable drive can contain an\n // individually-protected member this caller cannot read.\n const driveWorldReadable = await this.authorizationService.canRead(\n driveId,\n undefined,\n );\n if (driveWorldReadable) {\n await this.#collectForbiddenDocuments(\n remote.channel.outbox.items,\n forbiddenIds,\n ctx,\n );\n }\n // Dead letters can carry documents outside this collection (failed\n // inbox jobs) that the drive gate does not cover, so always filter.\n await this.#collectForbiddenDocuments(\n remote.channel.deadLetter.items,\n forbiddenIds,\n ctx,\n );\n }\n\n // Tier 2/3 again, from the document's own policy this time. The two\n // verdicts are intersected rather than swapped: every document\n // predating the policy migration reads as uninitialized, so trusting\n // the policy alone would open whatever the host's tables still\n // protect. Held entries are withheld, not consumed, so a grant that\n // widens later serves them whole on the next poll.\n // One snapshot feeds both the gate and the poll. Re-reading the\n // outbox after the gate's awaits would let an entry queued in the\n // meantime through with no verdict attached to it.\n const gate = this.syncServingGate;\n const gated = gate\n ? [\n ...remote.channel.outbox.items,\n ...remote.channel.deadLetter.items,\n ]\n : undefined;\n const heldOpIds =\n gate && gated\n ? await resolvers.collectHeldSyncOperations(\n gated,\n gate,\n this.viewSubject(ctx),\n )\n : new Set<string>();\n\n const { envelopes, ackOrdinal, deadLetters, hasMore } =\n resolvers.pollSyncEnvelopes(\n this.syncManager,\n args,\n forbiddenIds,\n heldOpIds,\n gated && new Set(gated.map((syncOp) => syncOp.id)),\n );\n return {\n envelopes,\n ackOrdinal,\n deadLetters,\n hasMore,\n };\n } catch (error) {\n this.logger.error(\n \"Error in pollSyncEnvelopes(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n },\n\n Mutation: {\n createDocument: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"createDocument(@args)\", args);\n try {\n // If creating under a parent, check write permission on parent\n if (args.parentIdentifier) {\n const parent = await resolvers.document(this.reactorClient, {\n identifier: args.parentIdentifier,\n });\n\n await this.assertCanWriteCanonical(\n parent.document.id as CanonicalDocumentId,\n ctx,\n );\n } else {\n this.assertCanCreate(ctx);\n }\n const result = await resolvers.createDocument(\n this.reactorClient,\n args,\n this.graphqlManager.reactorDriveClient,\n this.viewSubject(ctx),\n );\n\n if (result?.id && isDriveContainerType(result.documentType)) {\n this.graphqlManager.driveOwnershipCache.add(result.id);\n }\n\n // Auto-ownership: set creator as document owner\n if (ctx.user?.address && result?.id) {\n await this.documentPermissionService?.initializeDocumentProtection(\n result.id,\n ctx.user.address,\n this.authorizationService.config.defaultProtection,\n );\n }\n\n return result;\n } catch (error) {\n this.logger.error(\n \"Error in createDocument(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n createEmptyDocument: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"createEmptyDocument(@args)\", args);\n try {\n // If creating under a parent, check write permission on parent\n if (args.parentIdentifier) {\n const parent = await resolvers.document(this.reactorClient, {\n identifier: args.parentIdentifier,\n });\n\n await this.assertCanWriteCanonical(\n parent.document.id as CanonicalDocumentId,\n ctx,\n );\n } else {\n this.assertCanCreate(ctx);\n }\n const result = await resolvers.createEmptyDocument(\n this.reactorClient,\n args,\n this.graphqlManager.reactorDriveClient,\n this.viewSubject(ctx),\n );\n\n if (result?.id && isDriveContainerType(result.documentType)) {\n this.graphqlManager.driveOwnershipCache.add(result.id);\n }\n\n // Auto-ownership: set creator as document owner\n if (ctx.user?.address && result?.id) {\n await this.documentPermissionService?.initializeDocumentProtection(\n result.id,\n ctx.user.address,\n this.authorizationService.config.defaultProtection,\n );\n }\n\n return result;\n } catch (error) {\n this.logger.error(\n \"Error in createEmptyDocument(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n execute: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"execute(@args)\", args);\n try {\n // canMutate combines the write + operation checks per action.\n const handle = await this.assertCanExecuteOperations(\n args.documentIdentifier,\n args.actions,\n ctx,\n );\n\n return await resolvers.execute(\n this.reactorClient,\n { ...args, documentIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\"Error in execute(@args): @Error\", args, error);\n throw error;\n }\n },\n\n executeAsync: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"executeAsync(@args)\", args);\n try {\n const handle = await this.assertCanExecuteOperations(\n args.documentIdentifier,\n args.actions,\n ctx,\n );\n\n return await resolvers.executeAsync(this.reactorClient, {\n ...args,\n documentIdentifier: handle.fetchIdentifier,\n });\n } catch (error) {\n this.logger.error(\n \"Error in executeAsync(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n mutateDocument: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"mutateDocument(@args)\", args);\n try {\n // canMutate combines the write + operation checks per action.\n const handle = await this.assertCanExecuteOperations(\n args.documentIdentifier,\n args.actions,\n ctx,\n );\n\n return await resolvers.mutateDocument(\n this.reactorClient,\n { ...args, documentIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in mutateDocument(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n mutateDocumentAsync: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"mutateDocumentAsync(@args)\", args);\n try {\n const handle = await this.assertCanExecuteOperations(\n args.documentIdentifier,\n args.actions,\n ctx,\n );\n\n return await resolvers.mutateDocumentAsync(this.reactorClient, {\n ...args,\n documentIdentifier: handle.fetchIdentifier,\n });\n } catch (error) {\n this.logger.error(\n \"Error in mutateDocumentAsync(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n renameDocument: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"renameDocument(@args)\", args);\n try {\n const handle = await this.assertCanWrite(\n args.documentIdentifier,\n ctx,\n );\n\n return await resolvers.renameDocument(\n this.reactorClient,\n { ...args, documentIdentifier: handle.fetchIdentifier },\n undefined,\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in renameDocument(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n setPreferredEditor: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"setPreferredEditor(@args)\", args);\n try {\n const handle = await this.assertCanWrite(\n args.documentIdentifier,\n ctx,\n );\n\n return await resolvers.setPreferredEditor(\n this.reactorClient,\n { ...args, documentIdentifier: handle.fetchIdentifier },\n undefined,\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in setPreferredEditor(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n addRelationship: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"addRelationship(@args)\", args);\n try {\n const handle = await this.assertCanWrite(args.sourceIdentifier, ctx);\n\n return await resolvers.addRelationship(\n this.reactorClient,\n { ...args, sourceIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in addRelationship(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n updateRelationship: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"updateRelationship(@args)\", args);\n try {\n const handle = await this.assertCanWrite(args.sourceIdentifier, ctx);\n\n return await resolvers.updateRelationship(\n this.reactorClient,\n { ...args, sourceIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in updateRelationship(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n removeRelationship: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"removeRelationship(@args)\", args);\n try {\n const handle = await this.assertCanWrite(args.sourceIdentifier, ctx);\n\n return await resolvers.removeRelationship(\n this.reactorClient,\n { ...args, sourceIdentifier: handle.fetchIdentifier },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in removeRelationship(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n moveRelationship: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"moveRelationship(@args)\", args);\n try {\n const sourceHandle = await this.assertCanWrite(\n args.sourceParentIdentifier,\n ctx,\n );\n const targetHandle = await this.assertCanWrite(\n args.targetParentIdentifier,\n ctx,\n );\n\n return await resolvers.moveRelationship(\n this.reactorClient,\n {\n ...args,\n sourceParentIdentifier: sourceHandle.fetchIdentifier,\n targetParentIdentifier: targetHandle.fetchIdentifier,\n },\n this.viewSubject(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in moveRelationship(@args): @Error @args\",\n error,\n args,\n );\n throw error;\n }\n },\n\n deleteDocument: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"deleteDocument(@args)\", args);\n try {\n const handle = await this.assertCanWrite(args.identifier, ctx);\n const identifier = handle.fetchIdentifier;\n\n // Resolve identifier (id or slug) to detect drive deletes for cache\n // invalidation. Only one read; no-op for non-drive callers via the\n // catch.\n const driveIdToInvalidate = await this.#resolveDriveId(identifier);\n\n const result = await resolvers.deleteDocument(\n this.reactorClient,\n { ...args, identifier },\n this.graphqlManager.reactorDriveClient,\n );\n\n if (result && driveIdToInvalidate) {\n this.graphqlManager.driveOwnershipCache.remove(driveIdToInvalidate);\n }\n\n return result;\n } catch (error) {\n this.logger.error(\n \"Error in deleteDocument(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n deleteDocuments: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"deleteDocuments(@args)\", args);\n try {\n // Check write permission on each document, resolving slugs so the\n // delete targets the same canonical ids the checks authorized.\n const identifiers: string[] = [];\n for (const identifier of args.identifiers) {\n const handle = await this.assertCanWrite(identifier, ctx);\n identifiers.push(handle.fetchIdentifier);\n }\n return await resolvers.deleteDocuments(this.reactorClient, {\n ...args,\n identifiers,\n });\n } catch (error) {\n this.logger.error(\n \"Error in deleteDocuments(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n touchChannel: async (\n _parent: unknown,\n args: {\n input: {\n id: string;\n name: string;\n collectionId: string;\n filter: {\n documentId: readonly string[];\n scope: readonly string[];\n branch: string;\n };\n sinceTimestampUtcMs: string;\n };\n },\n ctx: Context,\n ) => {\n this.logger.debug(\"touchChannel(@args)\", args);\n\n try {\n // A channel synchronizes a collection, i.e. a drive. Registering one\n // requires read access to that drive; pushed operations are still\n // authorized per-operation in pushSyncEnvelopes. The collection id\n // carries the canonical drive id (never a slug).\n if (!this.authorizationService.isSupremeAdmin(ctx.user?.address)) {\n const driveId = DriveCollectionId.fromKey(args.input.collectionId)\n .driveId as CanonicalDocumentId;\n await this.assertCanReadCanonical(driveId, ctx);\n }\n\n await this.#bindOrRefuseChannel(args.input.id, ctx);\n\n return await resolvers.touchChannel(\n this.syncManager,\n args,\n this.#creatorBinding(ctx),\n );\n } catch (error) {\n this.logger.error(\n \"Error in touchChannel(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n\n pushSyncEnvelopes: async (_parent, args, ctx: Context) => {\n this.logger.debug(\"pushSyncEnvelopes(@args)\", args);\n\n try {\n // A push claims or proves ownership exactly as a poll does. It has to\n // be checked here rather than left to the per-operation canMutate\n // loop below, because an envelope carrying no operations skips that\n // loop entirely -- and a push stamps channel liveness, so without\n // this anyone who learns a channel id could keep that channel, and\n // the operations it is holding, alive for good.\n const boundChannelIds = new Set<string>();\n for (const envelope of args.envelopes) {\n const channelId = envelope.channelMeta.id;\n if (boundChannelIds.has(channelId)) continue;\n boundChannelIds.add(channelId);\n await this.#bindOrRefuseChannel(channelId, ctx, {\n adopt: false,\n action: \"push to\",\n });\n }\n\n // Check canMutate per distinct (documentId, action type). Nested map\n // rather than a joined key: a separator could be forged to collide\n // two distinct pairs and skip a check.\n const checkedOperations = new Map<string, Set<string>>();\n for (const envelope of args.envelopes) {\n for (const op of envelope.operations ?? []) {\n const documentId = op.context.documentId;\n const operationType = op.operation.action.type;\n let checkedTypes = checkedOperations.get(documentId);\n if (!checkedTypes) {\n checkedTypes = new Set<string>();\n checkedOperations.set(documentId, checkedTypes);\n }\n if (checkedTypes.has(operationType)) continue;\n checkedTypes.add(operationType);\n // Operation context ids are canonical document ids supplied by the\n // sync protocol (never slugs) and may reference documents not yet\n // materialized locally, so check them without slug resolution.\n await this.assertCanExecuteOperationCanonical(\n documentId as CanonicalDocumentId,\n operationType,\n ctx,\n );\n }\n }\n\n // Convert readonly arrays to mutable arrays for the resolver\n const mutableArgs = {\n envelopes: args.envelopes.map((envelope) => ({\n type: envelope.type,\n channelMeta: { id: envelope.channelMeta.id },\n operations: envelope.operations\n ? envelope.operations.map((op) => ({\n operation: op.operation,\n context: {\n documentId: op.context.documentId,\n documentType: op.context.documentType,\n scope: op.context.scope,\n branch: op.context.branch,\n ordinal: op.context.ordinal,\n },\n }))\n : null,\n cursor: envelope.cursor\n ? {\n remoteName: envelope.cursor.remoteName,\n cursorOrdinal: envelope.cursor.cursorOrdinal,\n lastSyncedAtUtcMs: envelope.cursor.lastSyncedAtUtcMs,\n }\n : null,\n key: envelope.key ?? undefined,\n dependsOn: envelope.dependsOn\n ? [...envelope.dependsOn]\n : undefined,\n })),\n };\n\n return await resolvers.pushSyncEnvelopes(\n this.syncManager,\n mutableArgs,\n );\n } catch (error) {\n this.logger.error(\n \"Error in pushSyncEnvelopes(@args): @Error\",\n args,\n error,\n );\n throw error;\n }\n },\n },\n\n Subscription: {\n documentChanges: {\n // Each subscriber reads the reactor's feed as its own subject, so the\n // client withholds what the policy refuses it. The predicate adds the\n // host's legacy check; both transports share this resolver.\n subscribe: (\n rootValue: unknown,\n args: {\n search?: { type?: string | null; parentId?: string | null } | null;\n },\n ctx: Context,\n info: unknown,\n ) => {\n this.logger.debug(\"documentChanges subscription started\");\n const filtered = withFilter<\n DocumentChangesPayload,\n {\n search?: {\n type?: string | null;\n parentId?: string | null;\n } | null;\n },\n Context\n >(\n () => this.documentChanges.subscribe(this.viewSubject(ctx)),\n async (payload, filterArgs, filterCtx) => {\n if (!payload) return false;\n\n const search = {\n type: filterArgs?.search?.type ?? undefined,\n parentId: filterArgs?.search?.parentId ?? undefined,\n };\n if (!matchesSearchFilter(payload.documentChanges, search)) {\n return false;\n }\n\n if (\n this.authorizationService.isSupremeAdmin(\n filterCtx?.user?.address,\n )\n ) {\n return true;\n }\n\n const documentIds = collectChangedDocumentIds(\n payload.documentChanges,\n );\n if (documentIds.length === 0) return false;\n for (const documentId of documentIds) {\n const canRead = await this.canReadDocument(\n documentId as CanonicalDocumentId,\n filterCtx as Context,\n );\n if (!canRead) return false;\n }\n return true;\n },\n );\n return filtered(rootValue as DocumentChangesPayload, args, ctx, info);\n },\n resolve: (payload: DocumentChangesPayload) => {\n return toGqlDocumentChangeEvent(payload.documentChanges);\n },\n },\n\n jobChanges: {\n // Drop events unless the subscriber can read the job's document.\n subscribe: (\n rootValue: unknown,\n args: { jobId: string },\n ctx: Context,\n info: unknown,\n ) => {\n this.logger.debug(\"jobChanges(@args) subscription started\", args);\n const filtered = withFilter<\n JobChangesPayload,\n { jobId: string },\n Context\n >(\n () => {\n ensureJobSubscription(this.reactorClient, args.jobId);\n return getPubSub().asyncIterableIterator<JobChangesPayload>(\n SUBSCRIPTION_TRIGGERS.JOB_CHANGES,\n );\n },\n async (payload, filterArgs, filterCtx) => {\n if (!payload || !filterArgs) return false;\n if (!matchesJobFilter(payload, filterArgs)) return false;\n if (\n !(await this.servesDocument(\n payload.documentId,\n filterCtx as Context,\n ))\n ) {\n return false;\n }\n\n if (\n this.authorizationService.isSupremeAdmin(\n filterCtx?.user?.address,\n )\n ) {\n return true;\n }\n\n if (!payload.documentId) return false;\n return this.canReadDocument(\n payload.documentId as CanonicalDocumentId,\n filterCtx as Context,\n );\n },\n );\n return filtered(rootValue as JobChangesPayload, args, ctx, info);\n },\n resolve: (payload: JobChangesPayload) => {\n return payload.jobChanges;\n },\n },\n },\n };\n\n onSetup(): Promise<void> {\n this.logger.debug(\"Setting up ReactorSubgraph\");\n\n return Promise.resolve();\n }\n}\n","export const getAdminUsers = (): string[] => {\n return (\n process.env.ADMIN_USERS?.split(\",\").map((user) =>\n user.trim().toLocaleLowerCase(),\n ) || []\n );\n};\n","import dotenv from \"dotenv\";\nimport { getAdminUsers } from \"./getters.js\";\n\n// `dotenv.config()` reads a .env file relative to `process.cwd()`. This module\n// is pulled in whenever a package's subgraph is loaded, including by the\n// reactor's CDN/edge package loader, whose runtime has no full `process`\n// (`process.cwd` is not a function). Calling it there throws\n// \"process.cwd is not a function\" and aborts package loading. Guard it: only\n// load a .env file in a real Node context — elsewhere env already lives in\n// `process.env`, so there is nothing to load.\nif (typeof process !== \"undefined\" && typeof process.cwd === \"function\") {\n dotenv.config();\n}\n\nexport const ADMIN_USERS = getAdminUsers();\n","import { buildTreeUrl } from \"@powerhousedao/shared\";\n\ndeclare const REACTOR_API_VERSION: string | undefined;\ndeclare const REACTOR_API_GIT_SHA: string | undefined;\n\nexport function getVersion(): string {\n if (typeof REACTOR_API_VERSION !== \"undefined\") return REACTOR_API_VERSION;\n return (\n process.env.WORKSPACE_VERSION ??\n process.env.npm_package_version ??\n \"unknown\"\n );\n}\n\nexport function getGitHash(): string {\n if (typeof REACTOR_API_GIT_SHA !== \"undefined\") return REACTOR_API_GIT_SHA;\n return process.env.WORKSPACE_GIT_SHA ?? \"unknown\";\n}\n\nexport function getGitUrl(): string | null {\n return buildTreeUrl(getGitHash());\n}\n","import { gql } from \"graphql-tag\";\nimport { BaseSubgraph } from \"../base-subgraph.js\";\nimport { getGitHash, getGitUrl, getVersion } from \"./version.js\";\n\nexport class SystemSubgraph extends BaseSubgraph {\n name = \"system\";\n hasSubscriptions = false;\n\n typeDefs = gql`\n type SystemInfo {\n version: String!\n gitHash: String!\n gitUrl: String\n }\n\n type Query {\n system: SystemInfo!\n }\n `;\n\n resolvers = {\n Query: {\n system: () => ({\n version: getVersion(),\n gitHash: getGitHash(),\n gitUrl: getGitUrl(),\n }),\n },\n };\n}\n","import type { IDocumentModelLoader } from \"@powerhousedao/reactor\";\nimport type { SubgraphClass } from \"@powerhousedao/reactor-api\";\nimport type {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport { childLogger } from \"document-model\";\nimport type { IPackageLoader, ProcessorFactoryBuilder } from \"../types.js\";\nimport { piecesFromCdnList } from \"./pieces.js\";\nimport type { PackagePieceEntry } from \"./types.js\";\nimport { extractUpgradeManifests } from \"./util.js\";\n\nexport interface HttpPackageLoaderOptions {\n registryUrl: string;\n}\n\nexport interface HttpPackageLoaderLogger {\n info: (msg: string) => void;\n error: (msg: string, err: unknown) => void;\n}\n\n// A published package.json version: never a range or a dist-tag.\nconst EXACT_VERSION =\n /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$/;\n\n// Where a package version's pieces are served; exact, so an entryUrl never floats.\nexport function piecesBaseUrl(\n registryUrl: string,\n packageName: string,\n version: string,\n): string {\n const root = registryUrl.endsWith(\"/\") ? registryUrl : `${registryUrl}/`;\n return `${root}-/cdn/${packageName}@${version}/node/pieces/`;\n}\n\n// Expected shape of the document-models bundle export\ntype DocumentModelsExport = Record<string, DocumentModelModule>;\n\n// Expected shape of the subgraphs bundle export\ntype SubgraphsExport = Record<string, SubgraphClass>;\n\n/**\n * Extract subgraph classes from the imported subgraphs/index.mjs module shape.\n *\n * The published bundle uses `export * as Foo from \"./file\"`, which Node turns\n * into `{ Foo: <namespace>, … }`. The inner namespace's keys come from the\n * source file's named exports — typically `Subgraph` / `default` / the class\n * name itself — so the shape varies. Flatten one level and keep callables.\n *\n * Exported for direct unit testing against synthetic module shapes.\n */\nexport function extractSubgraphsFromModule(\n module: Record<string, SubgraphsExport>,\n): SubgraphClass[] {\n return Object.values(module)\n .flatMap((namespace) => Object.values(namespace))\n .filter((s): s is SubgraphClass => typeof s === \"function\");\n}\n\n// Expected shape of the processors bundle export\ntype ProcessorsExport = {\n processorFactory?: ProcessorFactoryBuilder;\n};\n\n/**\n * Loads document models, subgraphs, and processors from an HTTP registry.\n * Uses Node.js module loader hooks to import directly from HTTP URLs.\n *\n * IMPORTANT: Requires https-hooks to be registered before use:\n * import { register } from \"node:module\";\n * register(\"@powerhousedao/reactor-api/https-hooks\", import.meta.url);\n */\nexport class HttpPackageLoader implements IPackageLoader {\n private readonly registryUrl: string;\n private readonly logger = childLogger([\"reactor-api\", \"http-loader\"]);\n\n readonly name = \"HttpPackageLoader\";\n\n readonly documentModelLoader: HttpDocumentModelLoader;\n\n constructor(options: HttpPackageLoaderOptions) {\n this.registryUrl = options.registryUrl.endsWith(\"/\")\n ? options.registryUrl\n : `${options.registryUrl}/`;\n this.documentModelLoader = new HttpDocumentModelLoader(this);\n }\n\n /**\n * Load document models from a package in the HTTP registry.\n * Imports directly from HTTP URL using Node.js loader hooks.\n */\n /**\n * Parse a package specifier like \"@scope/pkg@tag\" into name and optional tag.\n */\n private parsePackageSpec(spec: string): {\n name: string;\n tag: string | undefined;\n } {\n if (spec.startsWith(\"@\")) {\n const lastAt = spec.lastIndexOf(\"@\");\n if (lastAt > 0 && lastAt !== spec.indexOf(\"@\")) {\n return { name: spec.slice(0, lastAt), tag: spec.slice(lastAt + 1) };\n }\n return { name: spec, tag: undefined };\n }\n const atIndex = spec.indexOf(\"@\");\n if (atIndex > 0) {\n return { name: spec.slice(0, atIndex), tag: spec.slice(atIndex + 1) };\n }\n return { name: spec, tag: undefined };\n }\n\n async loadDocumentModels(\n packageSpec: string,\n ): Promise<DocumentModelModule[]> {\n const { name: packageName } = this.parsePackageSpec(packageSpec);\n if (!this.isValidPackageName(packageName)) {\n throw new Error(`Invalid package name: ${packageName}`);\n }\n\n // Pass the full spec (with tag) to the CDN — the registry resolves it\n const url = `${this.registryUrl}-/cdn/${packageSpec}/node/document-models/index.mjs`;\n\n this.logger.verbose(`Importing document-models from: ${url}`);\n\n // Direct import from HTTP URL - hooks handle the fetch\n const module = (await import(url)) as DocumentModelsExport;\n\n const models = Object.values(module).filter(\n (m: unknown): m is DocumentModelModule =>\n m !== null &&\n typeof m === \"object\" &&\n \"documentModel\" in m &&\n m.documentModel !== null,\n );\n\n this.logger.verbose(\n `Loaded ${models.length} document models from ${packageName}`,\n );\n return models;\n }\n\n async loadUpgradeManifests(\n packageSpec: string,\n ): Promise<UpgradeManifest<readonly number[]>[]> {\n const { name: packageName } = this.parsePackageSpec(packageSpec);\n if (!this.isValidPackageName(packageName)) {\n throw new Error(`Invalid package name: ${packageName}`);\n }\n\n const url = `${this.registryUrl}-/cdn/${packageSpec}/node/document-models/index.mjs`;\n const module = (await import(url)) as Record<string, unknown>;\n\n const manifests = extractUpgradeManifests(module);\n if (manifests.length > 0) {\n this.logger.verbose(\n `Loaded ${manifests.length} upgrade manifests from ${packageName}`,\n );\n }\n return manifests;\n }\n\n async loadSubgraphs(packageSpec: string): Promise<SubgraphClass[]> {\n const { name: packageName } = this.parsePackageSpec(packageSpec);\n if (!this.isValidPackageName(packageName)) {\n throw new Error(`Invalid package name: ${packageName}`);\n }\n\n const url = `${this.registryUrl}-/cdn/${packageSpec}/node/subgraphs/index.mjs`;\n\n this.logger.verbose(`Importing subgraphs from: ${url}`);\n const module = (await import(url)) as Record<string, SubgraphsExport>;\n const subgraphs = extractSubgraphsFromModule(module);\n\n this.logger.verbose(\n `Loaded ${subgraphs.length} subgraphs from ${packageName}`,\n );\n return subgraphs;\n }\n\n async loadProcessors(\n packageSpec: string,\n ): Promise<ProcessorFactoryBuilder | null> {\n const { name: packageName } = this.parsePackageSpec(packageSpec);\n if (!this.isValidPackageName(packageName)) {\n throw new Error(`Invalid package name: ${packageName}`);\n }\n\n const url = `${this.registryUrl}-/cdn/${packageSpec}/node/processors/index.mjs`;\n\n this.logger.verbose(`Importing processors from: ${url}`);\n const module = (await import(url)) as ProcessorsExport;\n\n const factory = module.processorFactory;\n if (factory && typeof factory === \"function\") {\n this.logger.verbose(`Loaded processor factory from ${packageName}`);\n return factory;\n }\n\n this.logger.verbose(`No processor factory found in ${packageName}`);\n return null;\n }\n\n // The same list module every other loader reads, on the CDN path its three\n // siblings already come from. Metadata only: no piece code is fetched here.\n\n // The declared entry is relative to the package root while the CDN serves\n // beneath `dist/`, so this is the only place that can make it absolute.\n async loadPieces(packageSpec: string): Promise<PackagePieceEntry[]> {\n const { name: packageName } = this.parsePackageSpec(packageSpec);\n if (!this.isValidPackageName(packageName)) {\n throw new Error(`Invalid package name: ${packageName}`);\n }\n // Pinned before anything is read: a tag or an unversioned spec would let\n // every entryUrl float to whatever the registry serves next.\n const version = await this.packageVersion(packageSpec);\n if (!version) {\n this.logger.verbose(`No package version found for: ${packageSpec}`);\n return [];\n }\n const base = piecesBaseUrl(this.registryUrl, packageName, version);\n this.logger.verbose(`Importing pieces from: ${base}index.mjs`);\n let module: unknown;\n try {\n module = await import(`${base}index.mjs`);\n } catch (error) {\n // A package shipping none has no list to serve, which is the common\n // case rather than a fault.\n this.logger.verbose(`No pieces found for: ${packageName}`, error);\n return [];\n }\n const pieces = piecesFromCdnList(\n module,\n base,\n packageName,\n this.logger,\n version,\n );\n this.logger.verbose(`Loaded ${pieces.length} pieces from ${packageName}`);\n return pieces;\n }\n\n /**\n * Load document models from multiple packages.\n * Continues loading even if some packages fail.\n */\n async loadPackages(\n packageNames: string[],\n logger?: HttpPackageLoaderLogger,\n ): Promise<DocumentModelModule[]> {\n const allModels: DocumentModelModule[] = [];\n\n for (const pkgName of packageNames) {\n const trimmedName = pkgName.trim();\n if (!trimmedName) continue;\n\n try {\n const models = await this.loadDocumentModels(trimmedName);\n allModels.push(...models);\n const logMsg = `Loaded ${models.length} document models from ${trimmedName}`;\n logger?.info(logMsg);\n this.logger.info(logMsg);\n } catch (error) {\n const errMsg = `Failed to load package ${trimmedName}`;\n logger?.error(errMsg, error);\n this.logger.error(errMsg, error);\n // Continue with other packages - don't fail startup\n }\n }\n\n return allModels;\n }\n\n // The exact version a spec resolves to, read off the package.json the CDN serves.\n async packageVersion(packageSpec: string): Promise<string | undefined> {\n try {\n const response = await fetch(\n `${this.registryUrl}-/cdn/${packageSpec}/package.json`,\n );\n if (!response.ok) return undefined;\n const pkg = (await response.json()) as { version?: unknown };\n return typeof pkg.version === \"string\" && EXACT_VERSION.test(pkg.version)\n ? pkg.version\n : undefined;\n } catch (error) {\n this.logger.verbose(\n `Could not read the version of ${packageSpec}`,\n error,\n );\n return undefined;\n }\n }\n\n private isValidPackageName(name: string): boolean {\n // npm package name pattern: optional scope + package name\n const pattern = /^(@[a-z0-9][-a-z0-9._]*\\/)?[a-z0-9][-a-z0-9._]*$/i;\n return pattern.test(name) && !name.includes(\"..\") && name.length <= 214;\n }\n}\n\n/**\n * Returns live modules (host-only sources): dynamically loaded models are\n * registered on the host registry but never reach executor worker threads.\n * Making them worker-executable means returning an importable source here\n * (the CDN URL as a package specifier, given process-wide https hooks).\n */\nexport class HttpDocumentModelLoader implements IDocumentModelLoader {\n private readonly loader: HttpPackageLoader;\n private readonly logger = childLogger([\n \"reactor-api\",\n \"http-document-model-loader\",\n ]);\n\n // Cache: documentType -> packageName\n private readonly documentTypeCache = new Map<string, string>();\n\n // Cache: packageName -> DocumentModelModule[]\n private readonly packageModulesCache = new Map<\n string,\n DocumentModelModule[]\n >();\n\n private onModelLoaded?: (model: DocumentModelModule) => void;\n\n constructor(loader: HttpPackageLoader) {\n this.loader = loader;\n }\n\n setOnModelLoaded(callback: (model: DocumentModelModule) => void): void {\n this.onModelLoaded = callback;\n }\n\n clearCache(): void {\n this.documentTypeCache.clear();\n this.packageModulesCache.clear();\n }\n\n async load(documentType: string): Promise<DocumentModelModule> {\n const packageName = await this.findPackageByDocumentType(documentType);\n\n let models: DocumentModelModule[];\n\n const cachedModels = this.packageModulesCache.get(packageName);\n if (cachedModels) {\n models = cachedModels;\n } else {\n models = await this.loader.loadDocumentModels(packageName);\n this.packageModulesCache.set(packageName, models);\n }\n\n const model = models.find(\n (m) => m.documentModel.global.id === documentType,\n );\n\n if (!model) {\n const availableTypes = models.map((m) => m.documentModel.global.id);\n throw new Error(\n `Document model ${documentType} not found in package ${packageName}. ` +\n `Available types: ${availableTypes.join(\", \")}`,\n );\n }\n\n this.logger.info(\n `Loaded document model \"${documentType}\" from package \"${packageName}\"`,\n );\n\n if (this.onModelLoaded) {\n this.onModelLoaded(model);\n }\n\n return model;\n }\n\n private async findPackageByDocumentType(\n documentType: string,\n ): Promise<string> {\n const cached = this.documentTypeCache.get(documentType);\n if (cached) {\n return cached;\n }\n\n const encodedType = encodeURIComponent(documentType);\n const url = `${this.loader[\"registryUrl\"]}packages/by-document-type?type=${encodedType}`;\n\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(\n `Registry query failed for document type ${documentType}: ${response.status} ${response.statusText}`,\n );\n }\n\n const packageNames = (await response.json()) as string[];\n\n if (packageNames.length === 0) {\n throw new Error(\n `No package found containing document type: ${documentType}`,\n );\n }\n\n const packageName = packageNames.sort((a, b) => a.localeCompare(b))[0];\n this.documentTypeCache.set(documentType, packageName);\n\n return packageName;\n }\n\n getLoadedPackages(): string[] {\n return Array.from(this.packageModulesCache.keys());\n }\n\n getPackageModules(packageName: string): DocumentModelModule[] | undefined {\n return this.packageModulesCache.get(packageName);\n }\n\n removeFromCache(packageName: string): void {\n this.packageModulesCache.delete(packageName);\n for (const [docType, pkg] of this.documentTypeCache) {\n if (pkg === packageName) {\n this.documentTypeCache.delete(docType);\n }\n }\n }\n}\n","import type { SubgraphClass } from \"@powerhousedao/reactor-api\";\nimport type {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport { childLogger } from \"document-model\";\nimport { existsSync } from \"node:fs\";\nimport { isAbsolute, join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { IPackageLoader, ProcessorFactoryBuilder } from \"../types.js\";\nimport {\n PIECE_SOURCE_LIST,\n pieceListLocation,\n piecesFromListModule,\n} from \"./pieces.js\";\nimport type { PackagePieceEntry } from \"./types.js\";\nimport {\n extractUpgradeManifests,\n loadDocumentModels as loadDocumentModelsUtil,\n loadProcessors as loadProcessorsUtil,\n loadSubgraphs as loadSubgraphsUtil,\n} from \"./util.js\";\n\n/**\n * This class is used to load packages using the import keyword.\n */\nexport class ImportPackageLoader implements IPackageLoader {\n private readonly logger = childLogger([\"reactor-api\", \"import-loader\"]);\n\n readonly name = \"ImportPackageLoader\";\n\n // Where the host's own dependencies are installed; the process's cwd.\n constructor(private readonly hostDir = process.cwd()) {}\n\n // Said once per package: a project rebuilt while the reactor runs answers\n // on the next load, and repeating the advice every time would only nag.\n private readonly reportedUnbuilt = new Set<string>();\n\n async loadDocumentModels(identifier: string): Promise<DocumentModelModule[]> {\n this.logger.verbose(`Loading document models from package: ${identifier}`);\n\n const pkgModule = await loadDocumentModelsUtil(identifier);\n\n if (pkgModule) {\n // duck type: the namespace also carries non-module exports such as the\n // upgradeManifests aggregate\n const models = Object.values(pkgModule).filter(\n (m: unknown): m is DocumentModelModule =>\n m !== null && typeof m === \"object\" && \"documentModel\" in m,\n );\n this.logger.verbose(\n ` ➜ Loaded ${models.length} Document Models from: ${identifier}`,\n );\n return models;\n } else {\n this.logger.verbose(` ➜ No Document Models found: ${identifier}`);\n return [];\n }\n }\n\n async loadUpgradeManifests(\n identifier: string,\n ): Promise<UpgradeManifest<readonly number[]>[]> {\n const pkgModule = await loadDocumentModelsUtil(identifier);\n if (!pkgModule) return [];\n\n const manifests = extractUpgradeManifests(pkgModule);\n if (manifests.length > 0) {\n this.logger.verbose(\n ` ➜ Loaded ${manifests.length} Upgrade Manifests from: ${identifier}`,\n );\n }\n return manifests;\n }\n\n async loadSubgraphs(identifier: string): Promise<SubgraphClass[]> {\n this.logger.verbose(`Loading subgraphs from package: ${identifier}`);\n\n const pkgModule = await loadSubgraphsUtil(identifier);\n\n if (!pkgModule) {\n this.logger.verbose(` ➜ No Subgraphs found: ${identifier}`);\n\n return [];\n }\n\n const subgraphs = Object.values(pkgModule).map((subgraph) => {\n return Object.values(subgraph);\n });\n\n this.logger.verbose(` ➜ Loaded Subgraphs from: ${identifier}`);\n\n return subgraphs.flat();\n }\n\n async loadProcessors(\n identifier: string,\n ): Promise<ProcessorFactoryBuilder | null> {\n this.logger.verbose(`Loading processors from package: ${identifier}`);\n\n const pkgModule = await loadProcessorsUtil(identifier);\n\n const factory = pkgModule?.processorFactory;\n\n if (factory && typeof factory === \"function\") {\n this.logger.verbose(` ➜ Loaded Processor Factory from: ${identifier}`);\n return factory;\n }\n\n this.logger.verbose(` ➜ No Processor Factory found: ${identifier}`);\n return null;\n }\n\n // Only the list is imported, never a piece: the list is data, and a piece is\n // code that belongs in a worker under an egress policy.\n async loadPieces(identifier: string): Promise<PackagePieceEntry[]> {\n this.logger.verbose(`Loading pieces from package: ${identifier}`);\n\n // A name is left to throw, so the manager can read the resolution error's\n // shape; a path answers for itself, and an absent list means none.\n const { root, listPath } = pieceListLocation(identifier, this.hostDir);\n if (!existsSync(listPath)) {\n this.reportUnbuilt(identifier, root, listPath);\n return [];\n }\n\n const module: unknown = await import(\n /* @vite-ignore */ pathToFileURL(listPath).href\n );\n const pieces = piecesFromListModule(module, {\n root,\n identifier,\n logger: this.logger,\n });\n this.logger.verbose(\n ` ➜ Loaded ${pieces.length} Pieces from: ${identifier}`,\n );\n return pieces;\n }\n\n // A package with piece sources and no built list is half-built, which is a\n // different thing from one that ships no pieces and worth saying so.\n private reportUnbuilt(identifier: string, root: string, listPath: string) {\n if (!isAbsolute(identifier) || this.reportedUnbuilt.has(identifier)) return;\n if (!existsSync(join(root, PIECE_SOURCE_LIST))) return;\n this.reportedUnbuilt.add(identifier);\n this.logger.warn(\n \"@pkg declares pieces but @list was never built; run `ph build`\",\n identifier,\n listPath,\n );\n }\n}\n","import { getConfig } from \"@powerhousedao/config/node\";\nimport type {\n Processor,\n ProcessorFactoryBuilder,\n SubgraphClass,\n} from \"@powerhousedao/reactor-api\";\nimport { reactorDriveDocumentModelModule } from \"@powerhousedao/reactor-drive\";\nimport { ReactorGroupV1 } from \"@powerhousedao/reactor-group\";\nimport { driveDocumentModelModule } from \"@powerhousedao/shared/document-drive\";\nimport type {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport { childLogger, documentModelDocumentModelModule } from \"document-model\";\nimport EventEmitter from \"node:events\";\nimport type { StatWatcher } from \"node:fs\";\nimport { watchFile } from \"node:fs\";\nimport type {\n IPackageLoader,\n IPackageManager,\n IPackageManagerOptions,\n ISubscribablePackageLoader,\n PackageManagerResult,\n PackagePieceEntry,\n} from \"./types.js\";\nimport { debounce } from \"./util.js\";\n\n/**\n * A loader throwing \"this package isn't mine to load\" is normal — loaders are\n * fallbacks for each other. These shapes mean \"not found here\", not \"broken\".\n *\n * `ERR_MODULE_NOT_FOUND` is ambiguous: it can mean either (a) the loader's own\n * entry import for `pkg` failed (expected — the package isn't installed\n * locally), or (b) the entry loaded successfully but a *transitive* bare\n * import inside it couldn't resolve (real error — the bundle is broken). We\n * distinguish by checking whether the error names the package we asked for —\n * either bare (`'pkg'`) or as a subpath (`'pkg/subgraphs'`), since loaders\n * import sub-entries like `${pkg}/subgraphs` / `${pkg}/document-models`.\n */\n// `subPath` is the sub-entry that was asked for. With it, two more answers\n// read as misses: an `exports` map that omits it, and a 404 for it.\nexport function isExpectedLoaderMiss(\n error: unknown,\n pkg: string,\n subPath?: string,\n): boolean {\n if (!(error instanceof Error)) return false;\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"ERR_UNSUPPORTED_DIR_IMPORT\") return true; // empty subgraphs/ etc.\n // An `exports` map without this subpath is the package saying it ships none\n // — the same answer as a missing directory, in a package that declares one.\n if (\n code === \"ERR_PACKAGE_PATH_NOT_EXPORTED\" &&\n subPath !== undefined &&\n error.message.includes(`'./${subPath}'`)\n ) {\n return true;\n }\n // Nothing published at that subpath; any other status is a registry fault,\n // and a 404 naming anything else is a broken bundle, not a miss.\n if (\n subPath !== undefined &&\n new RegExp(`^Failed to fetch \\\\S*/${subPath}/index\\\\.mjs: 404$`).test(\n error.message,\n )\n ) {\n return true;\n }\n // HttpPackageLoader rejects local paths and invalid npm names before any fetch\n if (error.message.startsWith(\"Invalid package name:\")) return true;\n if (code === \"ERR_MODULE_NOT_FOUND\") {\n // Match `'pkg'`, `\"pkg\"`, `'pkg/...'`, or `\"pkg/...\"`. Anything else is a\n // transitive resolution failure inside a successfully-fetched bundle.\n return (\n error.message.includes(`'${pkg}'`) ||\n error.message.includes(`\"${pkg}\"`) ||\n error.message.includes(`'${pkg}/`) ||\n error.message.includes(`\"${pkg}/`)\n );\n }\n return false;\n}\n\nexport function getUniqueDocumentModels(\n ...documentModels: readonly (readonly DocumentModelModule<any>[])[]\n): DocumentModelModule[] {\n const uniqueModels = new Map<string, DocumentModelModule>();\n\n for (const models of documentModels) {\n for (const model of models) {\n // versions of a document type are distinct modules; keying by type\n // alone would keep only the last version of a versioned model\n uniqueModels.set(\n `${model.documentModel.global.id}@${model.version ?? 1}`,\n model,\n );\n }\n }\n\n return Array.from(uniqueModels.values());\n}\n\nexport function getUniqueUpgradeManifests(\n ...upgradeManifests: readonly (readonly UpgradeManifest<\n readonly number[]\n >[])[]\n): UpgradeManifest<readonly number[]>[] {\n const uniqueManifests = new Map<string, UpgradeManifest<readonly number[]>>();\n\n for (const manifests of upgradeManifests) {\n for (const manifest of manifests) {\n uniqueManifests.set(manifest.documentType, manifest);\n }\n }\n\n return Array.from(uniqueManifests.values());\n}\n\nexport class PackageManager implements IPackageManager {\n private readonly logger = childLogger([\"reactor-api\", \"package-manager\"]);\n private loaders: ISubscribablePackageLoader[];\n\n private docModelsMap = new Map<string, DocumentModelModule[]>();\n private upgradeManifestsMap = new Map<\n string,\n UpgradeManifest<readonly number[]>[]\n >();\n private subgraphsMap = new Map<string, SubgraphClass[]>();\n private processorMap = new Map<string, Processor>();\n private piecesMap = new Map<string, PackagePieceEntry[]>();\n private configWatcher: StatWatcher | undefined;\n private debouncedUpdateCallbacks = new Map<string, () => void>();\n private eventEmitter = new EventEmitter<{\n documentModelsChange: [Record<string, DocumentModelModule[]>];\n subgraphsChange: [Map<string, SubgraphClass[]>];\n processorsChange: [Map<string, Processor>];\n piecesChange: [Map<string, PackagePieceEntry[]>];\n }>();\n\n constructor(\n loaders: IPackageLoader[],\n protected options: IPackageManagerOptions,\n ) {\n this.loaders = loaders;\n this.eventEmitter.setMaxListeners(0);\n }\n\n public async init(): Promise<PackageManagerResult> {\n if (this.options.configFile) {\n this.initConfigFileWatcher(this.options.configFile);\n }\n\n return await this.loadPackages(this.getAllPackageNames());\n }\n\n private async loadPackages(\n packages: string[],\n ): Promise<PackageManagerResult> {\n this.logger.info(\"Loading packages: @packages\", packages.join(\", \"));\n\n const documentModelsMap = await this.loadDocumentModels(packages);\n const upgradeManifestsMap = await this.loadUpgradeManifests(packages);\n const subgraphsMap = await this.loadSubgraphs(packages);\n const processorsMap = await this.loadProcessors(packages);\n const piecesMap = await this.loadPieces(packages);\n\n this.upgradeManifestsMap = upgradeManifestsMap;\n this.updatePackagesMap(documentModelsMap);\n this.updateSubgraphsMap(subgraphsMap);\n this.updateProcessorsMap(processorsMap);\n this.updatePiecesMap(piecesMap);\n\n try {\n this.subscribePackages(packages);\n } catch (error) {\n this.logger.error(\"Failed to subscribe to packages: @error\", error);\n }\n\n return {\n documentModels: getUniqueDocumentModels(\n ...Array.from(documentModelsMap.values()),\n ),\n upgradeManifests: this.getUniqueUpgradeManifests(),\n subgraphs: subgraphsMap,\n processors: processorsMap,\n pieces: piecesMap,\n };\n }\n\n private async loadDocumentModels(\n packages: string[],\n ): Promise<Map<string, DocumentModelModule[]>> {\n this.logger.debug(\n `Loading document models from packages: ${packages.join(\", \")}`,\n );\n\n const documentModelModuleMap = new Map<string, DocumentModelModule[]>();\n\n // static prereqs\n documentModelModuleMap.set(\"document-drive\", [\n driveDocumentModelModule as unknown as DocumentModelModule,\n ]);\n\n documentModelModuleMap.set(\"document-model\", [\n documentModelDocumentModelModule as unknown as DocumentModelModule,\n ]);\n\n documentModelModuleMap.set(\"reactor-drive\", [\n reactorDriveDocumentModelModule as unknown as DocumentModelModule,\n ]);\n\n documentModelModuleMap.set(\"reactor-group\", [\n ReactorGroupV1 as unknown as DocumentModelModule,\n ]);\n\n for (const pkg of packages) {\n const allDocumentModels: DocumentModelModule[] = [];\n const failures: { loader: string; error: unknown }[] = [];\n let succeeded = false;\n\n for (const loader of this.loaders) {\n try {\n const documentModels = await loader.loadDocumentModels(pkg);\n\n allDocumentModels.push(...documentModels);\n this.logger.info(\n `[${loader.name}] Loaded document models from package @pkg: @documentModels`,\n pkg,\n documentModels.map((dm) => dm.documentModel.global.id),\n );\n succeeded = true;\n break;\n } catch (error) {\n failures.push({ loader: loader.name, error });\n this.logger.debug(\n `[${loader.name}] Failed to load document models from package @pkg: @error`,\n pkg,\n error,\n );\n }\n }\n\n this.maybeWarnAllLoadersFailed(\n \"document models\",\n pkg,\n succeeded,\n failures,\n );\n\n documentModelModuleMap.set(pkg, allDocumentModels);\n }\n\n return documentModelModuleMap;\n }\n\n /** Upgrade manifests currently loaded across all packages, one per type. */\n public getUniqueUpgradeManifests(): UpgradeManifest<readonly number[]>[] {\n return getUniqueUpgradeManifests(\n ...Array.from(this.upgradeManifestsMap.values()),\n );\n }\n\n private async loadUpgradeManifests(\n packages: string[],\n ): Promise<Map<string, UpgradeManifest<readonly number[]>[]>> {\n const manifestsMap = new Map<\n string,\n UpgradeManifest<readonly number[]>[]\n >();\n\n for (const pkg of packages) {\n for (const loader of this.loaders) {\n if (!loader.loadUpgradeManifests) continue;\n try {\n const manifests = await loader.loadUpgradeManifests(pkg);\n if (manifests.length > 0) {\n manifestsMap.set(pkg, manifests);\n break;\n }\n } catch (error) {\n this.logger.debug(\n `[${loader.name}] Failed to load upgrade manifests from package @pkg: @error`,\n pkg,\n error,\n );\n }\n }\n }\n\n return manifestsMap;\n }\n\n private async loadSubgraphs(\n packages: string[],\n ): Promise<Map<string, SubgraphClass[]>> {\n this.logger.debug(\n `Loading subgraphs from packages: ${packages.join(\", \")}`,\n );\n\n const subgraphsMap = new Map<string, SubgraphClass[]>();\n\n for (const pkg of packages) {\n const allSubgraphs: SubgraphClass[] = [];\n const failures: { loader: string; error: unknown }[] = [];\n let succeeded = false;\n\n for (const loader of this.loaders) {\n try {\n const subgraphs = await loader.loadSubgraphs(pkg);\n\n allSubgraphs.push(...subgraphs);\n succeeded = true;\n break;\n } catch (error) {\n failures.push({ loader: loader.name, error });\n this.logger.debug(\n `[${loader.name}] Failed to load subgraphs from package ${pkg}`,\n error,\n );\n }\n }\n\n this.maybeWarnAllLoadersFailed(\"subgraphs\", pkg, succeeded, failures);\n\n subgraphsMap.set(pkg, allSubgraphs);\n }\n\n return subgraphsMap;\n }\n\n private async loadProcessors(\n packages: string[],\n ): Promise<Map<string, Processor>> {\n this.logger.debug(\n `Loading processors from packages: ${packages.join(\", \")}`,\n );\n\n const processorsMap = new Map<string, Processor>();\n\n for (const pkg of packages) {\n const allProcessors: ProcessorFactoryBuilder[] = [];\n const failures: { loader: string; error: unknown }[] = [];\n let succeeded = false;\n\n for (const loader of this.loaders) {\n try {\n const processors = await loader.loadProcessors(pkg);\n\n if (processors) {\n allProcessors.push(processors);\n }\n succeeded = true;\n break;\n } catch (error) {\n failures.push({ loader: loader.name, error });\n this.logger.debug(\n `[${loader.name}] Failed to load processors from package ${pkg}`,\n error,\n );\n }\n }\n\n this.maybeWarnAllLoadersFailed(\"processors\", pkg, succeeded, failures);\n\n processorsMap.set(pkg, allProcessors);\n }\n\n return processorsMap;\n }\n\n // Paths, not modules: a piece is code the host must not import, and what a\n // worker needs from here is where on disk the package put it.\n private async loadPieces(\n packages: string[],\n ): Promise<Map<string, PackagePieceEntry[]>> {\n this.logger.debug(`Loading pieces from packages: ${packages.join(\", \")}`);\n\n const piecesMap = new Map<string, PackagePieceEntry[]>();\n\n for (const pkg of packages) {\n const allPieces: PackagePieceEntry[] = [];\n const failures: { loader: string; error: unknown }[] = [];\n let succeeded = false;\n\n for (const loader of this.loaders) {\n try {\n allPieces.push(...(await loader.loadPieces(pkg)));\n succeeded = true;\n break;\n } catch (error) {\n failures.push({ loader: loader.name, error });\n this.logger.debug(\n `[${loader.name}] Failed to load pieces from package ${pkg}`,\n error,\n );\n }\n }\n\n this.maybeWarnAllLoadersFailed(\"pieces\", pkg, succeeded, failures);\n\n if (allPieces.length > 0) {\n this.logger.info(\n \"Loaded @count piece(s) from package @pkg: @pieces\",\n allPieces.length,\n pkg,\n allPieces.map((piece) => piece.name).join(\", \"),\n );\n }\n piecesMap.set(pkg, allPieces);\n }\n\n return piecesMap;\n }\n\n private maybeWarnAllLoadersFailed(\n kind: \"document models\" | \"subgraphs\" | \"processors\" | \"pieces\",\n pkg: string,\n succeeded: boolean,\n failures: { loader: string; error: unknown }[],\n ): void {\n if (succeeded || failures.length === 0) return;\n // The package subpath every loader asked for, which is what tells a\n // package that ships none of this kind from one whose bundle is broken.\n const subPath = kind === \"document models\" ? \"document-models\" : kind;\n // Each loader's \"this package isn't mine\" failure is expected fallthrough,\n // not a real error. Only surface a warning when at least one loader hit\n // something unexpected (e.g. a bundle evaluation error or registry 5xx),\n // and show only those non-expected failures — expected misses would just\n // mislead the reader about which loader actually broke.\n const realFailures = failures.filter(\n ({ error }) => !isExpectedLoaderMiss(error, pkg, subPath),\n );\n if (realFailures.length === 0) return;\n\n const details = realFailures\n .map(({ loader, error }) => {\n const message = error instanceof Error ? error.message : String(error);\n return ` [${loader}] ${message}`;\n })\n .join(\"\\n\");\n this.logger.warn(\n `All package loaders failed to load ${kind} from @pkg:\\n@details`,\n pkg,\n details,\n );\n }\n\n private async updateDocumentModelsForPackage(pkg: string): Promise<void> {\n this.logger.debug(`Updating document models for package: ${pkg}`);\n const documentModels = await this.loadDocumentModels([pkg]);\n const upgradeManifests = await this.loadUpgradeManifests([pkg]);\n const upgradeManifestsMap = new Map(this.upgradeManifestsMap);\n const pkgManifests = upgradeManifests.get(pkg) ?? [];\n if (pkgManifests.length === 0) {\n upgradeManifestsMap.delete(pkg);\n } else {\n upgradeManifestsMap.set(pkg, pkgManifests);\n }\n this.upgradeManifestsMap = upgradeManifestsMap;\n const documentModelsMap = new Map(this.docModelsMap);\n const pkgModels = documentModels.get(pkg) ?? [];\n if (pkgModels.length === 0) {\n // An empty result means the package no longer contributes document\n // models: drop the key so the change event signals removal instead of\n // re-asserting an empty entry.\n documentModelsMap.delete(pkg);\n } else {\n documentModelsMap.set(pkg, pkgModels);\n }\n this.updatePackagesMap(documentModelsMap);\n }\n\n private async updateSubgraphsForPackage(pkg: string): Promise<void> {\n this.logger.debug(`Updating subgraphs for package: ${pkg}`);\n const subgraphs = await this.loadSubgraphs([pkg]);\n const subgraphsMap = new Map(this.subgraphsMap);\n const pkgSubgraphs = subgraphs.get(pkg) ?? [];\n if (pkgSubgraphs.length === 0) {\n // An empty result means the package no longer contributes subgraphs\n // (e.g. its subgraphs/ entry was removed): drop the key so the change\n // event signals removal instead of re-asserting an empty entry.\n subgraphsMap.delete(pkg);\n } else {\n subgraphsMap.set(pkg, pkgSubgraphs);\n }\n this.updateSubgraphsMap(subgraphsMap);\n }\n\n private async updateProcessorsForPackage(pkg: string): Promise<void> {\n this.logger.debug(`Updating processors for package: ${pkg}`);\n const processors = await this.loadProcessors([pkg]);\n const processorsMap = new Map(this.processorMap);\n const pkgProcessors = processors.get(pkg) ?? [];\n if (pkgProcessors.length === 0) {\n processorsMap.delete(pkg);\n } else {\n processorsMap.set(pkg, pkgProcessors);\n }\n this.updateProcessorsMap(processorsMap);\n }\n\n private async updatePiecesForPackage(pkg: string): Promise<void> {\n this.logger.debug(`Updating pieces for package: ${pkg}`);\n const pieces = await this.loadPieces([pkg]);\n const piecesMap = new Map(this.piecesMap);\n const pkgPieces = pieces.get(pkg) ?? [];\n if (pkgPieces.length === 0) {\n // An empty result means the package no longer contributes pieces: drop\n // the key so the change event signals removal, as its siblings do.\n piecesMap.delete(pkg);\n } else {\n piecesMap.set(pkg, pkgPieces);\n }\n this.updatePiecesMap(piecesMap);\n }\n\n /** Debounced per key so repeated subscribePackages calls reuse one timer. */\n private getDebouncedUpdateCallback(\n key: string,\n update: () => Promise<void>,\n ): () => void {\n if (!this.debouncedUpdateCallbacks.has(key)) {\n const debouncedFn = debounce(update, 1000);\n this.debouncedUpdateCallbacks.set(key, () => {\n debouncedFn().catch((error: unknown) => {\n this.logger.error(\"Failed to update package: @error\", error);\n });\n });\n }\n return this.debouncedUpdateCallbacks.get(key)!;\n }\n\n private subscribePackages(packages: string[]) {\n const unsubs: (() => void)[] = [];\n for (const pkg of packages) {\n const onDocumentModels = this.getDebouncedUpdateCallback(\n `${pkg}:document-models`,\n () => this.updateDocumentModelsForPackage(pkg),\n );\n const onSubgraphs = this.getDebouncedUpdateCallback(\n `${pkg}:subgraphs`,\n () => this.updateSubgraphsForPackage(pkg),\n );\n const onProcessors = this.getDebouncedUpdateCallback(\n `${pkg}:processors`,\n () => this.updateProcessorsForPackage(pkg),\n );\n const onPieces = this.getDebouncedUpdateCallback(`${pkg}:pieces`, () =>\n this.updatePiecesForPackage(pkg),\n );\n\n for (const loader of this.loaders) {\n if (loader.onDocumentModelsChange) {\n unsubs.push(loader.onDocumentModelsChange(pkg, onDocumentModels));\n }\n if (loader.onSubgraphsChange) {\n unsubs.push(loader.onSubgraphsChange(pkg, onSubgraphs));\n }\n if (loader.onProcessorsChange) {\n unsubs.push(loader.onProcessorsChange(pkg, onProcessors));\n }\n if (loader.onPiecesChange) {\n unsubs.push(loader.onPiecesChange(pkg, onPieces));\n }\n }\n }\n\n return () => {\n for (const unsub of unsubs) {\n unsub();\n }\n };\n }\n\n private getAllPackageNames(): string[] {\n const packageNames = this.options.packages ?? [];\n if (this.options.configFile) {\n packageNames.push(\n ...this.getPackageNamesFromConfigFile(this.options.configFile),\n );\n }\n return packageNames;\n }\n\n private getPackageNamesFromConfigFile(configFile: string) {\n const loadedConfig = getConfig(configFile);\n return loadedConfig.packages?.map((pkg) => pkg.packageName) ?? [];\n }\n\n private initConfigFileWatcher(configFile: string) {\n if (!this.configWatcher) {\n this.configWatcher = watchFile(\n configFile,\n { interval: 100 },\n (curr, prev) => {\n if (curr.mtime === prev.mtime) {\n return;\n }\n\n void this.loadPackages(this.getAllPackageNames());\n },\n );\n }\n }\n\n private updatePackagesMap(packagesMap: Map<string, DocumentModelModule[]>) {\n const oldPackages = Array.from(this.docModelsMap.keys());\n const newPackages = Array.from(packagesMap.keys());\n oldPackages\n .filter((pkg) => !newPackages.includes(pkg))\n .forEach((pkg) => {\n this.logger.info(`Removed package: ${pkg}`);\n });\n this.docModelsMap = packagesMap;\n this.eventEmitter.emit(\n \"documentModelsChange\",\n Object.fromEntries(packagesMap),\n );\n }\n\n private updateSubgraphsMap(subgraphsMap: Map<string, SubgraphClass[]>) {\n const oldPackages = Array.from(this.subgraphsMap.keys());\n const newPackages = Array.from(subgraphsMap.keys());\n oldPackages\n .filter((pkg) => !newPackages.includes(pkg))\n .forEach((pkg) => {\n this.logger.info(`Removed Subgraphs from: ${pkg}`);\n });\n this.subgraphsMap = subgraphsMap;\n this.eventEmitter.emit(\"subgraphsChange\", subgraphsMap);\n }\n\n private updateProcessorsMap(processorsMap: Map<string, Processor>) {\n const oldPackages = Array.from(this.processorMap.keys());\n const newPackages = Array.from(processorsMap.keys());\n oldPackages\n .filter((pkg) => !newPackages.includes(pkg))\n .forEach((pkg) => {\n this.logger.info(`Removed Processor Factories from: ${pkg}`);\n });\n\n this.processorMap = processorsMap;\n this.eventEmitter.emit(\"processorsChange\", processorsMap);\n }\n\n private updatePiecesMap(piecesMap: Map<string, PackagePieceEntry[]>) {\n const oldPackages = Array.from(this.piecesMap.keys());\n const newPackages = Array.from(piecesMap.keys());\n oldPackages\n .filter((pkg) => !newPackages.includes(pkg))\n .forEach((pkg) => {\n this.logger.info(\"Removed pieces from: @pkg\", pkg);\n });\n\n this.piecesMap = piecesMap;\n this.eventEmitter.emit(\"piecesChange\", piecesMap);\n }\n\n /** The pieces every loaded package ships, keyed by the package. */\n getPieces(): Map<string, PackagePieceEntry[]> {\n return new Map(this.piecesMap);\n }\n\n /**\n * Remove `pkg` from all package maps and emit the change events, tearing\n * down everything the package registered (subgraphs, processors, document\n * models). For an uninstalled package no loader can serve it again, so\n * nothing can re-add it.\n */\n removePackage(pkg: string): void {\n this.logger.info(`Removing package: ${pkg}`);\n const dropKey = <T>(map: Map<string, T>): Map<string, T> => {\n if (!map.has(pkg)) return map;\n const next = new Map(map);\n next.delete(pkg);\n return next;\n };\n\n this.docModelsMap = dropKey(this.docModelsMap);\n this.upgradeManifestsMap = dropKey(this.upgradeManifestsMap);\n this.subgraphsMap = dropKey(this.subgraphsMap);\n this.processorMap = dropKey(this.processorMap);\n this.piecesMap = dropKey(this.piecesMap);\n\n this.updatePackagesMap(this.docModelsMap);\n this.updateSubgraphsMap(this.subgraphsMap);\n this.updateProcessorsMap(this.processorMap);\n this.updatePiecesMap(this.piecesMap);\n }\n\n onDocumentModelsChange(\n handler: (documentModels: Record<string, DocumentModelModule[]>) => void,\n ): void {\n this.eventEmitter.on(\"documentModelsChange\", handler);\n }\n\n onSubgraphsChange(\n handler: (subgraphs: Map<string, SubgraphClass[]>) => void,\n ): void {\n this.eventEmitter.on(\"subgraphsChange\", handler);\n }\n\n onProcessorsChange(\n handler: (processors: Map<string, Processor>) => void,\n ): void {\n this.eventEmitter.on(\"processorsChange\", handler);\n }\n\n onPiecesChange(\n handler: (pieces: Map<string, PackagePieceEntry[]>) => void,\n ): void {\n this.eventEmitter.on(\"piecesChange\", handler);\n }\n}\n","import { AnalyticsSubgraph } from \"./graphql/analytics-subgraph.js\";\nimport { SystemSubgraph } from \"./graphql/system/subgraph.js\";\n\nexport const config = {\n basePath: process.env.BASE_PATH || \"/\",\n};\n\nexport const DefaultCoreSubgraphs = [\n AnalyticsSubgraph,\n SystemSubgraph,\n] as const;\n","import {\n createS3AttachmentBackend,\n parseAttachmentStorageConfig,\n type AttachmentDatabase,\n type IAttachmentBackend,\n type S3AttachmentBackendDependencies,\n} from \"@powerhousedao/reactor-attachments\";\nimport type { Kysely } from \"kysely\";\n\nexport type StartupAttachmentBackendOptions = {\n db: Kysely<AttachmentDatabase>;\n env?: Readonly<Record<string, string | undefined>>;\n s3Dependencies?: S3AttachmentBackendDependencies;\n};\n\n/** Filesystem is the default; explicit S3 is readiness-gated without fallback. */\nexport async function createStartupAttachmentBackend({\n db,\n env = process.env,\n s3Dependencies,\n}: StartupAttachmentBackendOptions): Promise<IAttachmentBackend | undefined> {\n const storage = parseAttachmentStorageConfig(env);\n if (storage.kind === \"filesystem\") return undefined;\n\n const backend = createS3AttachmentBackend(\n db.withSchema(\"attachments\"),\n storage.s3,\n s3Dependencies,\n );\n const health = await backend.health();\n if (!health.ready) {\n throw new Error(\"S3 attachment backend readiness check failed\");\n }\n return backend;\n}\n","import type {\n AttachmentHash,\n AttachmentRef,\n IReactorClient,\n} from \"@powerhousedao/reactor\";\nimport { createRef, parseRef } from \"@powerhousedao/reactor-attachments\";\nimport type { IAttachmentReferenceReader } from \"@powerhousedao/reactor-attachments\";\nimport type {\n CanonicalDocumentId,\n IAuthorizationService,\n} from \"./authorization.service.js\";\nimport type { CanonicalDocumentIdResolver } from \"./canonical-document-id.js\";\n\n/**\n * Whether the active Reactor composition hosts the attachment-reference\n * projection. Reported by the client initializer: the built-in stack always\n * registers it, while a caller-provided Reactor may lack the live\n * registration capability. Consumers of reference evidence must fail closed\n * when it is unavailable.\n */\nexport type AttachmentReferenceProjectionCapability =\n | { status: \"available\" }\n | {\n status: \"unavailable\";\n reason:\n | \"live-read-model-registration-unsupported\"\n | \"in-process-reactor-module-unavailable\"\n | \"initializer-did-not-report\";\n };\n\n/**\n * Outcome of an attachment read authorization. `denied` intentionally covers\n * both an unreadable document and an absent document/ref relationship so the\n * route layer cannot leak which check failed. `projection-unavailable` means\n * the reference index is not being maintained in this composition; it is\n * returned before any document-authorization or reference lookup runs.\n */\nexport type AttachmentAccessResult =\n | { kind: \"allowed\"; documentId: CanonicalDocumentId; ref: AttachmentRef }\n | { kind: \"denied\" }\n | { kind: \"projection-unavailable\" };\n\nexport interface AttachmentAccessRequest {\n documentId: string;\n attachmentRef: string;\n userAddress?: string;\n /**\n * The `did:key` of the app instance whose token authenticated the caller.\n * A policy subject is an address AND a key — a grant can name either, and a\n * document's creator is recorded by key — so a decision made from the address\n * alone answers a narrower question than the one being asked.\n */\n appKey?: string;\n}\n\n/** The reactor's read gate, as the attachment facade consults it. */\nexport type AttachmentReadGate = Pick<IReactorClient, \"isServed\" | \"get\">;\n\n/**\n * Which scopes of a document a subject may read, asked by document id.\n *\n * Structural on purpose: the composition that has a policy model to enforce\n * supplies `SyncScopeGate`, and one that does not supplies nothing at all.\n */\nexport interface IDocumentScopeGate {\n scopePredicateById(\n documentId: string,\n subject: { address?: string; key?: string },\n branch: string,\n signal?: AbortSignal,\n ): Promise<(scope: string) => boolean>;\n}\n\n/** The scope an attachment's bytes belong to: the document's own domain state. */\nconst ATTACHMENT_SCOPE = \"global\";\n\n/** The branch an attachment reference is resolved against. */\nconst ATTACHMENT_BRANCH = \"main\";\n\nexport interface IAttachmentAccessService {\n canReadAttachment(\n request: AttachmentAccessRequest,\n ): Promise<AttachmentAccessResult>;\n}\n\nconst HASH_PATTERN = /^[a-f0-9]{64}$/;\n\n/**\n * Composes document authorization with the projected document/ref\n * relationship. Order is fixed: validate ref, resolve the canonical document\n * id, decide the read, check the reactor's read gate serves the document, then\n * check the reference index and that the subject may read a scope whose\n * operations reference the attachment. A denied document never reaches the\n * reference reader, and the facade never touches attachment metadata, storage\n * backends, or presigners.\n *\n * The named document decides alone: an attachment several documents reference\n * is readable through each of them on that document's own terms.\n *\n * The read is decided by the document's own policy when this composition has a\n * model to enforce it with, and by the host's permission tables when it does\n * not. That is not a preference between two equivalent answers: a host running\n * document policies keeps no rows in the permission tables, so asking them\n * about such a document returns whatever the host-wide policy says — under\n * `OPEN`, `true`, for everyone. Serving bytes on that answer hands the file to\n * anyone who learns its hash, which the document's own state may well have told\n * them. Both are kept because they are the two halves of one rule: an\n * attachment is readable by whoever may read the document that references it,\n * and each composition can only express that in its own terms.\n */\nexport class AttachmentAccessService implements IAttachmentAccessService {\n constructor(\n private readonly resolveCanonicalId: CanonicalDocumentIdResolver,\n private readonly authorization: IAuthorizationService,\n private readonly references: IAttachmentReferenceReader,\n private readonly projection: AttachmentReferenceProjectionCapability,\n private readonly readGate: AttachmentReadGate,\n /**\n * Absent below auth enforcement, where there is no policy model to\n * evaluate; the host's permission tables decide alone, exactly as before.\n */\n private readonly scopeGate?: IDocumentScopeGate,\n ) {}\n\n async canReadAttachment(\n request: AttachmentAccessRequest,\n ): Promise<AttachmentAccessResult> {\n if (this.projection.status !== \"available\") {\n return { kind: \"projection-unavailable\" };\n }\n\n const ref = normalizeAttachmentRef(request.attachmentRef);\n if (ref === null) {\n return { kind: \"denied\" };\n }\n\n let documentId: CanonicalDocumentId;\n try {\n documentId = await this.resolveCanonicalId(request.documentId);\n } catch {\n return { kind: \"denied\" };\n }\n\n if (!(await this.canReadDocument(documentId, request))) {\n return { kind: \"denied\" };\n }\n\n const subject = { address: request.userAddress, key: request.appKey };\n\n let served: boolean;\n try {\n served = await this.readGate.isServed(documentId, { subject });\n } catch {\n return { kind: \"denied\" };\n }\n if (!served) {\n return { kind: \"denied\" };\n }\n\n const scopes = await this.references.referencingScopes(documentId, ref);\n if (scopes.length === 0) {\n return { kind: \"denied\" };\n }\n\n let held: Record<string, unknown>;\n try {\n const document = await this.readGate.get(documentId, {\n subject,\n scopes,\n });\n held = document.state as Record<string, unknown>;\n } catch {\n return { kind: \"denied\" };\n }\n if (!scopes.some((scope) => scope in held)) {\n return { kind: \"denied\" };\n }\n\n return { kind: \"allowed\", documentId, ref };\n }\n\n /**\n * Whether the caller may read the state the reference lives in.\n *\n * A failure here is rethrown rather than turned into a denial. A read side\n * that is down must not read as a policy: a denial nobody can distinguish\n * from a refusal is one nobody investigates, and the route answers 500 for a\n * reason.\n */\n private async canReadDocument(\n documentId: CanonicalDocumentId,\n request: AttachmentAccessRequest,\n ): Promise<boolean> {\n if (!this.scopeGate) {\n return this.authorization.canRead(documentId, request.userAddress);\n }\n const readable = await this.scopeGate.scopePredicateById(\n documentId,\n { address: request.userAddress, key: request.appKey },\n ATTACHMENT_BRANCH,\n );\n return readable(ATTACHMENT_SCOPE);\n }\n}\n\n/**\n * Parses and canonicalizes a caller-supplied ref through the shared parser.\n * Returns null for anything that is not a v1 ref over a 64-char SHA-256 hex\n * hash; hex case is normalized so index lookups use the canonical form.\n */\nfunction normalizeAttachmentRef(value: string): AttachmentRef | null {\n let hash: string;\n let version: number;\n try {\n const parsed = parseRef(value as AttachmentRef);\n hash = parsed.hash.toLowerCase();\n version = parsed.version;\n } catch {\n return null;\n }\n if (version !== 1 || !HASH_PATTERN.test(hash)) {\n return null;\n }\n return createRef(hash as AttachmentHash, version);\n}\n","import { getAuthContext } from \"./auth-middleware.js\";\nimport type { FetchHandler } from \"./types.js\";\n\nexport type RequireAuthFetchMiddleware = (\n handler: FetchHandler,\n) => FetchHandler;\n\n/**\n * Returns a fetch middleware that rejects anonymous callers with a 401.\n *\n * This is the enforcement half of the resolve-and-don't-enforce split set up\n * by `RESOLVE_CALLER_IDENTITY`: the auth middleware must run before this\n * one — it verifies the bearer (an invalid token is still a 401 from\n * there) and records the resolved caller on the request. This middleware\n * then refuses the request when no caller was resolved, so under `OPEN`\n * (or `AUTH_ENABLED` with identity resolution) the whole generic surface —\n * document CRUD, sync, every custom subgraph — is reachable only by\n * authenticated callers, without locking out non-admins the way\n * `ADMIN_ONLY` does.\n *\n * It composes in one place in the fetch chain, so it covers every mounted\n * subgraph, the supergraph, and the SSE handler alike.\n *\n * OPTIONS is let through: a CORS preflight never carries a bearer, and\n * `AuthService.authenticateRequest` already answers it with an anonymous\n * context — refusing it would break every cross-origin client with a 401.\n *\n * Fails closed: a request that reaches this middleware without a resolved\n * context has no caller, and is rejected. The server never composes this\n * middleware without the auth middleware in the chain (see\n * `assertRequireAuthenticatedCallerAllowed` in `server.ts`).\n *\n * `exemptPaths` names the mounted paths that stay reachable anonymously — a\n * deployment whose product has a flow that runs before sign-in, such as\n * previewing an invitation from its code, needs somewhere to serve it from.\n * Each entry is a hole in the floor, so the match is deliberately the\n * narrowest one that works: the request's pathname, compared in full. A\n * prefix rule would exempt `/graphql/public-admin` along with\n * `/graphql/public`, and an exempt surface nobody can enumerate by reading\n * the configuration is not one anybody audits.\n */\nexport function createRequireAuthFetchMiddleware(\n exemptPaths: readonly string[] = [],\n): RequireAuthFetchMiddleware {\n const exempt = new Set(exemptPaths.map(normalizeExemptPath));\n return (next: FetchHandler): FetchHandler =>\n async (request: globalThis.Request): Promise<globalThis.Response> => {\n if (request.method === \"OPTIONS\") {\n return next(request);\n }\n if (\n exempt.size > 0 &&\n exempt.has(normalizeExemptPath(new URL(request.url).pathname))\n ) {\n return next(request);\n }\n if (getAuthContext(request)?.user === undefined) {\n return new globalThis.Response(\n JSON.stringify({ error: \"Authentication required\" }),\n { status: 401 },\n );\n }\n return next(request);\n };\n}\n\n/**\n * The form both sides of the comparison are reduced to: surrounding whitespace\n * gone, and one trailing slash gone, so `/graphql/public/` and\n * `/graphql/public` are the same path. A client that appends a slash is not\n * asking for a different route, and a configuration that carries one is not\n * asking for a different rule.\n *\n * Deliberately NOT normalized: case, percent-encoding, and a missing leading\n * slash. The first two would let two spellings of one path diverge from how\n * the router itself matches; the third is a configuration error, and\n * `assertRequireAuthenticatedCallerAllowed` refuses to boot on it rather than\n * leaving an exemption that silently never applies.\n */\nfunction normalizeExemptPath(path: string): string {\n const trimmed = path.trim();\n return trimmed.length > 1 && trimmed.endsWith(\"/\")\n ? trimmed.slice(0, -1)\n : trimmed;\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<unknown>): Promise<void> {\n // Create DocumentPermission table\n await sql`\n CREATE TABLE IF NOT EXISTS \"DocumentPermission\" (\n \"id\" SERIAL PRIMARY KEY,\n \"documentId\" VARCHAR(255) NOT NULL,\n \"userAddress\" VARCHAR(255) NOT NULL,\n \"permission\" VARCHAR(20) NOT NULL CHECK (\"permission\" IN ('READ', 'WRITE', 'ADMIN')),\n \"grantedBy\" VARCHAR(255) NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n \"updatedAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n UNIQUE (\"documentId\", \"userAddress\")\n )\n `.execute(db);\n\n // Create indexes for DocumentPermission\n await sql`CREATE INDEX IF NOT EXISTS \"documentpermission_documentid_index\" ON \"DocumentPermission\" (\"documentId\")`.execute(\n db,\n );\n await sql`CREATE INDEX IF NOT EXISTS \"documentpermission_useraddress_index\" ON \"DocumentPermission\" (\"userAddress\")`.execute(\n db,\n );\n\n // Create Group table\n await sql`\n CREATE TABLE IF NOT EXISTS \"Group\" (\n \"id\" SERIAL PRIMARY KEY,\n \"name\" VARCHAR(255) NOT NULL UNIQUE,\n \"description\" TEXT,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n \"updatedAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n )\n `.execute(db);\n\n // Create UserGroup table (user-group membership)\n await sql`\n CREATE TABLE IF NOT EXISTS \"UserGroup\" (\n \"userAddress\" VARCHAR(255) NOT NULL,\n \"groupId\" INTEGER NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (\"userAddress\", \"groupId\")\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"usergroup_groupid_index\" ON \"UserGroup\" (\"groupId\")`.execute(\n db,\n );\n\n // Create DocumentGroupPermission table\n await sql`\n CREATE TABLE IF NOT EXISTS \"DocumentGroupPermission\" (\n \"id\" SERIAL PRIMARY KEY,\n \"documentId\" VARCHAR(255) NOT NULL,\n \"groupId\" INTEGER NOT NULL,\n \"permission\" VARCHAR(20) NOT NULL CHECK (\"permission\" IN ('READ', 'WRITE', 'ADMIN')),\n \"grantedBy\" VARCHAR(255) NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n \"updatedAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n UNIQUE (\"documentId\", \"groupId\")\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"documentgrouppermission_documentid_index\" ON \"DocumentGroupPermission\" (\"documentId\")`.execute(\n db,\n );\n await sql`CREATE INDEX IF NOT EXISTS \"documentgrouppermission_groupid_index\" ON \"DocumentGroupPermission\" (\"groupId\")`.execute(\n db,\n );\n\n // Create OperationUserPermission table\n await sql`\n CREATE TABLE IF NOT EXISTS \"OperationUserPermission\" (\n \"id\" SERIAL PRIMARY KEY,\n \"documentId\" VARCHAR(255) NOT NULL,\n \"operationType\" VARCHAR(255) NOT NULL,\n \"userAddress\" VARCHAR(255) NOT NULL,\n \"grantedBy\" VARCHAR(255) NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n UNIQUE (\"documentId\", \"operationType\", \"userAddress\")\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"operationuserpermission_documentid_index\" ON \"OperationUserPermission\" (\"documentId\")`.execute(\n db,\n );\n await sql`CREATE INDEX IF NOT EXISTS \"operationuserpermission_useraddress_index\" ON \"OperationUserPermission\" (\"userAddress\")`.execute(\n db,\n );\n\n // Create OperationGroupPermission table\n await sql`\n CREATE TABLE IF NOT EXISTS \"OperationGroupPermission\" (\n \"id\" SERIAL PRIMARY KEY,\n \"documentId\" VARCHAR(255) NOT NULL,\n \"operationType\" VARCHAR(255) NOT NULL,\n \"groupId\" INTEGER NOT NULL,\n \"grantedBy\" VARCHAR(255) NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n UNIQUE (\"documentId\", \"operationType\", \"groupId\")\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"operationgrouppermission_documentid_index\" ON \"OperationGroupPermission\" (\"documentId\")`.execute(\n db,\n );\n await sql`CREATE INDEX IF NOT EXISTS \"operationgrouppermission_groupid_index\" ON \"OperationGroupPermission\" (\"groupId\")`.execute(\n db,\n );\n}\n\nexport async function down(db: Kysely<unknown>): Promise<void> {\n await sql`DROP TABLE IF EXISTS \"OperationGroupPermission\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"OperationUserPermission\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"DocumentGroupPermission\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"UserGroup\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"Group\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"DocumentPermission\"`.execute(db);\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\nexport async function up(db: Kysely<unknown>): Promise<void> {\n await sql`\n CREATE TABLE IF NOT EXISTS \"DocumentProtection\" (\n \"documentId\" VARCHAR(255) PRIMARY KEY,\n \"protected\" BOOLEAN NOT NULL DEFAULT false,\n \"ownerAddress\" VARCHAR(255),\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n \"updatedAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"documentprotection_owneraddress_index\" ON \"DocumentProtection\" (\"ownerAddress\")`.execute(\n db,\n );\n await sql`CREATE INDEX IF NOT EXISTS \"documentprotection_protected_index\" ON \"DocumentProtection\" (\"protected\")`.execute(\n db,\n );\n}\n\nexport async function down(db: Kysely<unknown>): Promise<void> {\n await sql`DROP TABLE IF EXISTS \"DocumentProtection\"`.execute(db);\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\n\n/**\n * Removes the group-permission feature: the Group, UserGroup,\n * DocumentGroupPermission, and OperationGroupPermission tables. The feature had\n * no consumers and disclosed ACL/membership metadata (AUTH_REVIEW S-H3/S-H5);\n * it is retired in favor of direct user grants, ownership, and protection.\n *\n * Tables are dropped in reverse dependency order. There are no DB-enforced\n * foreign keys, so the drops cannot violate referential integrity and do not\n * touch the surviving DocumentPermission / OperationUserPermission /\n * DocumentProtection tables.\n */\nexport async function up(db: Kysely<unknown>): Promise<void> {\n await sql`DROP TABLE IF EXISTS \"OperationGroupPermission\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"DocumentGroupPermission\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"UserGroup\"`.execute(db);\n await sql`DROP TABLE IF EXISTS \"Group\"`.execute(db);\n}\n\nexport async function down(db: Kysely<unknown>): Promise<void> {\n // Recreate the group tables exactly as migration 001 created them.\n await sql`\n CREATE TABLE IF NOT EXISTS \"Group\" (\n \"id\" SERIAL PRIMARY KEY,\n \"name\" VARCHAR(255) NOT NULL UNIQUE,\n \"description\" TEXT,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n \"updatedAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP\n )\n `.execute(db);\n\n await sql`\n CREATE TABLE IF NOT EXISTS \"UserGroup\" (\n \"userAddress\" VARCHAR(255) NOT NULL,\n \"groupId\" INTEGER NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n PRIMARY KEY (\"userAddress\", \"groupId\")\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"usergroup_groupid_index\" ON \"UserGroup\" (\"groupId\")`.execute(\n db,\n );\n\n await sql`\n CREATE TABLE IF NOT EXISTS \"DocumentGroupPermission\" (\n \"id\" SERIAL PRIMARY KEY,\n \"documentId\" VARCHAR(255) NOT NULL,\n \"groupId\" INTEGER NOT NULL,\n \"permission\" VARCHAR(20) NOT NULL CHECK (\"permission\" IN ('READ', 'WRITE', 'ADMIN')),\n \"grantedBy\" VARCHAR(255) NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n \"updatedAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n UNIQUE (\"documentId\", \"groupId\")\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"documentgrouppermission_documentid_index\" ON \"DocumentGroupPermission\" (\"documentId\")`.execute(\n db,\n );\n await sql`CREATE INDEX IF NOT EXISTS \"documentgrouppermission_groupid_index\" ON \"DocumentGroupPermission\" (\"groupId\")`.execute(\n db,\n );\n\n await sql`\n CREATE TABLE IF NOT EXISTS \"OperationGroupPermission\" (\n \"id\" SERIAL PRIMARY KEY,\n \"documentId\" VARCHAR(255) NOT NULL,\n \"operationType\" VARCHAR(255) NOT NULL,\n \"groupId\" INTEGER NOT NULL,\n \"grantedBy\" VARCHAR(255) NOT NULL,\n \"createdAt\" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n UNIQUE (\"documentId\", \"operationType\", \"groupId\")\n )\n `.execute(db);\n\n await sql`CREATE INDEX IF NOT EXISTS \"operationgrouppermission_documentid_index\" ON \"OperationGroupPermission\" (\"documentId\")`.execute(\n db,\n );\n await sql`CREATE INDEX IF NOT EXISTS \"operationgrouppermission_groupid_index\" ON \"OperationGroupPermission\" (\"groupId\")`.execute(\n db,\n );\n}\n","import {\n Migrator,\n type Kysely,\n type Migration,\n type MigrationProvider,\n} from \"kysely\";\nimport * as migration001 from \"./001_create_document_permissions.js\";\nimport * as migration002 from \"./002_add_document_protection.js\";\nimport * as migration003 from \"./003_remove_group_tables.js\";\n\n/**\n * Custom migration provider that loads migrations from imported modules\n */\nclass StaticMigrationProvider implements MigrationProvider {\n getMigrations(): Promise<Record<string, Migration>> {\n return Promise.resolve({\n \"001_create_document_permissions\": migration001,\n \"002_add_document_protection\": migration002,\n \"003_remove_group_tables\": migration003,\n });\n }\n}\n\n/**\n * Run all pending migrations\n */\nexport async function runMigrations(db: Kysely<unknown>): Promise<void> {\n const migrator = new Migrator({\n db,\n provider: new StaticMigrationProvider(),\n });\n\n const { error, results } = await migrator.migrateToLatest();\n\n results?.forEach((result) => {\n if (result.status === \"Error\") {\n console.error(`Failed to execute migration \"${result.migrationName}\"`);\n }\n });\n\n if (error) {\n console.error(\"Failed to run migrations:\", error);\n const errorMessage =\n error instanceof Error ? error.message : \"Unknown error\";\n throw new Error(`Migration failed: ${errorMessage}`);\n }\n}\n\n/**\n * Rollback the last migration\n */\nexport async function rollbackMigration(db: Kysely<unknown>): Promise<void> {\n const migrator = new Migrator({\n db,\n provider: new StaticMigrationProvider(),\n });\n\n const { error, results } = await migrator.migrateDown();\n\n results?.forEach((result) => {\n if (result.status === \"Success\") {\n console.log(\n `Migration \"${result.migrationName}\" was rolled back successfully`,\n );\n } else if (result.status === \"Error\") {\n console.error(`Failed to rollback migration \"${result.migrationName}\"`);\n }\n });\n\n if (error) {\n console.error(\"Failed to rollback migration:\", error);\n const errorMessage =\n error instanceof Error ? error.message : \"Unknown error\";\n throw new Error(`Rollback failed: ${errorMessage}`);\n }\n}\n","import type { RouteUser } from \"@powerhousedao/shared/processors\";\nimport { verifyAuthBearerToken } from \"@renown/sdk\";\n\ntype VerifiedCredential =\n Awaited<ReturnType<typeof verifyAuthBearerToken>> extends false | (infer T)\n ? T\n : never;\n\n// Confirms an authenticated signer's credential is still valid. Injected so\n// AuthService stays agnostic to how/where credentials are verified.\nexport type CredentialVerifier = (params: {\n address: string;\n chainId: number;\n appId: string;\n}) => Promise<boolean>;\n\nexport interface AuthConfig {\n /**\n * Whether the authorization policy enforces anything: it selects `ADMIN_ONLY`\n * over `OPEN`, and it is what `AuthContext.auth_enabled` reports to callers\n * that gate on \"is authentication being enforced\" (the attachment routes do).\n *\n * It does NOT decide whether the bearer is read — see {@link resolveIdentity}.\n */\n enabled: boolean;\n /**\n * Whether the bearer is verified and `AuthContext.user` populated at all.\n *\n * Defaults to {@link enabled}, which is the behaviour every deployment had\n * before this option existed. Setting it independently is what lets a server\n * know who is calling while leaving the policy `OPEN` — resolving an identity\n * and enforcing one are different concerns, and welding them together left\n * consumers choosing between an unauthenticated caller and locking every\n * non-admin out.\n *\n * It resolves an identity and enforces nothing: a request with no token is\n * still admitted, with no user.\n */\n resolveIdentity?: boolean;\n admins: string[];\n skipCredentialVerification?: boolean; // DANGER: removes identity verification; boot-gated to test/dev\n credentialVerificationCacheTtlMs?: number; // How long successful Renown credential checks are cached; 0 disables caching\n verifyCredential?: CredentialVerifier; // Injected credential check; required when verification is on\n}\n\nconst DEFAULT_CREDENTIAL_CACHE_TTL_MS = 60_000;\nconst CREDENTIAL_CACHE_MAX_ENTRIES = 1_000;\n\ninterface CredentialCacheEntry {\n exists: Promise<boolean>;\n expiresAt: number;\n}\n\n/**\n * The authenticated principal. The shape is declared once in\n * `@powerhousedao/shared/processors` as `RouteUser`, so a route handler and a\n * resolver agree on it without either package redeclaring it.\n */\nexport type User = RouteUser;\n\nexport interface AuthContext {\n user?: User;\n admins: string[];\n auth_enabled: boolean;\n}\n\nexport class AuthService {\n private readonly config: AuthConfig;\n private readonly credentialCache = new Map<string, CredentialCacheEntry>();\n\n constructor(config: AuthConfig) {\n this.config = config;\n }\n\n /**\n * Whether this service reads the bearer at all. Defaults to `enabled`, so a\n * config written before `resolveIdentity` existed behaves exactly as it did.\n */\n private get resolvesIdentity(): boolean {\n return this.config.resolveIdentity ?? this.config.enabled;\n }\n\n /** The context an unresolved request gets: no user, and no admin list to match against. */\n private anonymousContext(): AuthContext {\n return { user: undefined, admins: [], auth_enabled: this.config.enabled };\n }\n\n async authenticateRequest(\n request: globalThis.Request,\n ): Promise<AuthContext | globalThis.Response> {\n if (!this.resolvesIdentity) {\n return this.anonymousContext();\n }\n // OPTIONS is a CORS preflight: it never carries application auth. Every\n // other method verifies whatever token it carries -- a GET query's payload\n // can be an authorization verdict, so discarding its token would silently\n // answer for the anonymous subject instead of the authenticated caller.\n // A GET without a token stays anonymous, as verifyBearer already allows.\n if (request.method === \"OPTIONS\") {\n return {\n user: undefined,\n admins: this.config.admins,\n auth_enabled: this.config.enabled,\n };\n }\n return this.verifyBearer(request.headers.get(\"authorization\") ?? undefined);\n }\n\n /**\n * Verify a Bearer token regardless of HTTP method. Use this from non-GraphQL\n * middleware that must enforce authentication on every request.\n */\n async verifyBearer(\n authorization: string | undefined,\n ): Promise<AuthContext | globalThis.Response> {\n if (!this.resolvesIdentity) {\n return this.anonymousContext();\n }\n const token = authorization?.split(\" \")[1];\n if (!token) {\n return {\n user: undefined,\n admins: this.config.admins,\n auth_enabled: this.config.enabled,\n };\n }\n try {\n const verified = await this.verifyToken(token);\n if (!verified) {\n return new Response(JSON.stringify({ error: \"Verification failed\" }), {\n status: 401,\n });\n }\n const user = this.extractUserFromVerification(verified);\n if (!user) {\n return new Response(JSON.stringify({ error: \"Missing credentials\" }), {\n status: 401,\n });\n }\n if (!this.config.skipCredentialVerification) {\n const credentialExists = await this.verifyCredentialExists(\n user.address,\n user.chainId,\n verified.issuer,\n );\n if (!credentialExists) {\n return new Response(\n JSON.stringify({ error: \"Credentials no longer valid\" }),\n { status: 401 },\n );\n }\n }\n return {\n user,\n admins: this.config.admins,\n auth_enabled: this.config.enabled,\n };\n } catch {\n return new Response(JSON.stringify({ error: \"Authentication failed\" }), {\n status: 401,\n });\n }\n }\n\n // `null` when there is nobody to resolve: resolution off, or no bearer sent.\n\n /** Throws only for a bearer that is present and unusable, as HTTP 401s it. */\n async authenticateWebSocketConnection(\n connectionParams: Record<string, unknown>,\n ): Promise<User | null> {\n if (!this.resolvesIdentity) {\n return null;\n }\n\n const authHeader = connectionParams.authorization as string | undefined;\n if (!authHeader) {\n // Resolution, not enforcement: `verifyBearer` answers the same.\n\n // Refusing anonymous is onConnect's, keyed on REQUIRE_AUTHENTICATED_CALLER.\n\n // Subscriptions themselves authorize per document.\n return null;\n }\n\n const token = authHeader.split(\" \")[1];\n if (!token) {\n throw new Error(\"Invalid authorization format\");\n }\n\n const verified = await this.verifyToken(token);\n if (!verified) {\n throw new Error(\"Token verification failed\");\n }\n\n const user = this.extractUserFromVerification(verified);\n if (!user) {\n throw new Error(\"Invalid credentials\");\n }\n\n if (!this.config.skipCredentialVerification) {\n const credentialExists = await this.verifyCredentialExists(\n user.address,\n user.chainId,\n verified.issuer,\n );\n if (!credentialExists) {\n throw new Error(\"Credentials no longer valid\");\n }\n }\n\n // Note: We no longer block based on global allowed lists.\n // Authorization is handled at the resolver level based on document permissions.\n\n return user;\n }\n\n /**\n * Verify the auth bearer token\n */\n private async verifyToken(token: string) {\n return await verifyAuthBearerToken(token);\n }\n\n /**\n * Extract user information from verification result.\n *\n * The issuer is required along with the credential subject. A credential that\n * verified must carry one -- resolving it is how the signature was checked --\n * so this rejects a shape that cannot have come from verification rather than\n * admitting a keyless principal.\n */\n private extractUserFromVerification(\n verified: VerifiedCredential,\n ): User | null {\n try {\n const { address, chainId, networkId } =\n verified.verifiableCredential.credentialSubject;\n const appKey = verified.issuer;\n\n if (!address || !chainId || !networkId || !appKey) {\n return null;\n }\n\n return {\n address,\n chainId,\n networkId,\n appKey,\n };\n } catch {\n return null;\n }\n }\n\n /**\n * Verify that the credential still exists on the Renown API.\n *\n * Results are cached per (address, chainId, issuer) for a short TTL so the\n * blocking external round-trip is not paid on every request. Concurrent\n * checks for the same key share a single in-flight request, and entries\n * that resolve to false are evicted immediately so failed or revoked\n * credentials are re-checked on the next request.\n */\n private verifyCredentialExists(\n address: string,\n chainId: number,\n appId: string,\n ): Promise<boolean> {\n const ttlMs =\n this.config.credentialVerificationCacheTtlMs ??\n DEFAULT_CREDENTIAL_CACHE_TTL_MS;\n if (ttlMs <= 0) {\n return this.fetchCredentialExists(address, chainId, appId);\n }\n\n const key = `${address.toLowerCase()}:${chainId}:${appId}`;\n const now = Date.now();\n const cached = this.credentialCache.get(key);\n if (cached && cached.expiresAt > now) {\n return cached.exists;\n }\n\n this.pruneCredentialCache(now);\n const entry: CredentialCacheEntry = {\n exists: this.fetchCredentialExists(address, chainId, appId).then(\n (exists) => {\n if (!exists && this.credentialCache.get(key) === entry) {\n this.credentialCache.delete(key);\n }\n return exists;\n },\n ),\n expiresAt: now + ttlMs,\n };\n this.credentialCache.set(key, entry);\n return entry.exists;\n }\n\n /**\n * Enforce the cache size cap before inserting a new entry: drop expired\n * entries first, then evict oldest-inserted entries (insertion order\n * matches expiry order since the TTL is constant) until under the cap, so\n * a flood of distinct keys cannot grow the map without bound.\n */\n private pruneCredentialCache(now: number): void {\n if (this.credentialCache.size < CREDENTIAL_CACHE_MAX_ENTRIES) {\n return;\n }\n for (const [key, entry] of this.credentialCache) {\n if (entry.expiresAt <= now) {\n this.credentialCache.delete(key);\n }\n }\n while (this.credentialCache.size >= CREDENTIAL_CACHE_MAX_ENTRIES) {\n const oldestKey = this.credentialCache.keys().next().value;\n if (oldestKey === undefined) {\n break;\n }\n this.credentialCache.delete(oldestKey);\n }\n }\n\n // Confirm the signer's credential is still valid via the injected verifier.\n // Reached only when verification is on, so a missing verifier is misconfig.\n private async fetchCredentialExists(\n address: string,\n chainId: number,\n appId: string,\n ): Promise<boolean> {\n if (!this.config.verifyCredential) {\n throw new Error(\n \"AuthService: credential verification is enabled but no verifyCredential was provided\",\n );\n }\n return this.config.verifyCredential({ address, chainId, appId });\n }\n}\n","import {\n fetchDelegationCredential,\n resolveSwitchboardEndpoint,\n} from \"@renown/sdk\";\nimport type { CredentialVerifier } from \"./auth.service.js\";\n\nexport interface RenownCredentialVerifierConfig {\n // Renown base URL for the REST/discovery path. Defaults to the SDK default.\n renownUrl?: string;\n // Switchboard GraphQL endpoint; when reachable, read the reactor directly.\n switchboardUrl?: string;\n}\n\n// A CredentialVerifier backed by Renown. Resolves the switchboard endpoint once\n// at creation so each verify call skips discovery; falls back to REST otherwise.\nexport async function createRenownCredentialVerifier(\n config: RenownCredentialVerifierConfig = {},\n): Promise<CredentialVerifier> {\n const switchboardUrl = await resolveSwitchboardEndpoint({\n switchboardUrl: config.switchboardUrl,\n baseUrl: config.renownUrl,\n });\n\n return async ({ address, chainId, appId }) => {\n const credential = await fetchDelegationCredential({\n address,\n chainId,\n appDid: appId,\n // Endpoint resolved once at creation: use it, or REST — never re-discover.\n switchboardUrl,\n baseUrl: switchboardUrl ? undefined : config.renownUrl,\n discover: false,\n });\n return credential !== undefined;\n };\n}\n","import type { Kysely } from \"kysely\";\nimport { sql } from \"kysely\";\nimport type {\n DocumentPermissionDatabase,\n DocumentPermissionLevel,\n} from \"../utils/db.js\";\n\nexport interface DocumentPermissionEntry {\n documentId: string;\n userAddress: string;\n permission: DocumentPermissionLevel;\n grantedBy: string;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface OperationUserPermissionEntry {\n documentId: string;\n operationType: string;\n userAddress: string;\n grantedBy: string;\n createdAt: Date;\n}\n\n/**\n * Function type for getting parent document IDs\n * This is injected to avoid circular dependencies with the reactor client\n */\nexport type GetParentIdsFn = (documentId: string) => Promise<string[]>;\n\n/**\n * Configuration for the DocumentPermissionService\n */\nexport interface DocumentPermissionConfig {\n defaultProtection: boolean;\n}\n\n/**\n * Service for managing document-level permissions.\n *\n * Permission levels for documents:\n * - READ: Can fetch and read the document\n * - WRITE: Can push updates and modify the document\n * - ADMIN: Can manage document permissions and settings\n *\n * Operation permissions:\n * - Users can be granted permission to execute specific operations\n */\nexport class DocumentPermissionService {\n readonly config: DocumentPermissionConfig;\n\n constructor(\n private readonly db: Kysely<DocumentPermissionDatabase>,\n config: DocumentPermissionConfig = { defaultProtection: false },\n ) {\n this.config = config;\n }\n\n // ============================================\n // User Permission Operations\n // ============================================\n\n /**\n * Get the permission level for a user on a specific document.\n * Returns null if no permission is set.\n */\n async getUserPermission(\n documentId: string,\n userAddress: string,\n ): Promise<DocumentPermissionLevel | null> {\n const result = await this.db\n .selectFrom(\"DocumentPermission\")\n .select(\"permission\")\n .where(\"documentId\", \"=\", documentId)\n .where(\"userAddress\", \"=\", userAddress.toLowerCase())\n .executeTakeFirst();\n\n return result?.permission ?? null;\n }\n\n /**\n * Get all permissions for a document\n */\n async getDocumentPermissions(\n documentId: string,\n ): Promise<DocumentPermissionEntry[]> {\n const results = await this.db\n .selectFrom(\"DocumentPermission\")\n .select([\n \"documentId\",\n \"userAddress\",\n \"permission\",\n \"grantedBy\",\n \"createdAt\",\n \"updatedAt\",\n ])\n .where(\"documentId\", \"=\", documentId)\n .execute();\n\n return results;\n }\n\n /**\n * Get all documents a user has explicit access to\n */\n async getUserDocuments(\n userAddress: string,\n ): Promise<DocumentPermissionEntry[]> {\n const results = await this.db\n .selectFrom(\"DocumentPermission\")\n .select([\n \"documentId\",\n \"userAddress\",\n \"permission\",\n \"grantedBy\",\n \"createdAt\",\n \"updatedAt\",\n ])\n .where(\"userAddress\", \"=\", userAddress.toLowerCase())\n .execute();\n\n return results;\n }\n\n /**\n * Grant or update a user's permission on a document.\n */\n async grantPermission(\n documentId: string,\n userAddress: string,\n permission: DocumentPermissionLevel,\n grantedBy: string,\n ): Promise<DocumentPermissionEntry> {\n const now = new Date();\n const normalizedAddress = userAddress.toLowerCase();\n\n await this.db\n .insertInto(\"DocumentPermission\")\n .values({\n documentId,\n userAddress: normalizedAddress,\n permission,\n grantedBy: grantedBy.toLowerCase(),\n createdAt: now,\n updatedAt: now,\n })\n .onConflict((oc) =>\n oc.columns([\"documentId\", \"userAddress\"]).doUpdateSet({\n permission,\n grantedBy: grantedBy.toLowerCase(),\n updatedAt: now,\n }),\n )\n .execute();\n\n const result = await this.db\n .selectFrom(\"DocumentPermission\")\n .select([\n \"documentId\",\n \"userAddress\",\n \"permission\",\n \"grantedBy\",\n \"createdAt\",\n \"updatedAt\",\n ])\n .where(\"documentId\", \"=\", documentId)\n .where(\"userAddress\", \"=\", normalizedAddress)\n .executeTakeFirstOrThrow();\n\n return result;\n }\n\n /**\n * Revoke a user's permission on a document\n */\n async revokePermission(\n documentId: string,\n userAddress: string,\n ): Promise<void> {\n await this.db\n .deleteFrom(\"DocumentPermission\")\n .where(\"documentId\", \"=\", documentId)\n .where(\"userAddress\", \"=\", userAddress.toLowerCase())\n .execute();\n }\n\n /**\n * Delete all permissions for a document (used when deleting a document)\n */\n async deleteAllDocumentPermissions(documentId: string): Promise<void> {\n await this.db\n .deleteFrom(\"DocumentPermission\")\n .where(\"documentId\", \"=\", documentId)\n .execute();\n\n await this.db\n .deleteFrom(\"OperationUserPermission\")\n .where(\"documentId\", \"=\", documentId)\n .execute();\n }\n\n // ============================================\n // Operation Permissions\n // ============================================\n\n /**\n * Grant a user permission to execute an operation on a document\n */\n async grantOperationPermission(\n documentId: string,\n operationType: string,\n userAddress: string,\n grantedBy: string,\n ): Promise<OperationUserPermissionEntry> {\n const now = new Date();\n const normalizedAddress = userAddress.toLowerCase();\n\n await this.db\n .insertInto(\"OperationUserPermission\")\n .values({\n documentId,\n operationType,\n userAddress: normalizedAddress,\n grantedBy: grantedBy.toLowerCase(),\n createdAt: now,\n })\n .onConflict((oc) =>\n oc.columns([\"documentId\", \"operationType\", \"userAddress\"]).doNothing(),\n )\n .execute();\n\n const result = await this.db\n .selectFrom(\"OperationUserPermission\")\n .select([\n \"documentId\",\n \"operationType\",\n \"userAddress\",\n \"grantedBy\",\n \"createdAt\",\n ])\n .where(\"documentId\", \"=\", documentId)\n .where(\"operationType\", \"=\", operationType)\n .where(\"userAddress\", \"=\", normalizedAddress)\n .executeTakeFirstOrThrow();\n\n return result;\n }\n\n /**\n * Revoke a user's permission to execute an operation\n */\n async revokeOperationPermission(\n documentId: string,\n operationType: string,\n userAddress: string,\n ): Promise<void> {\n await this.db\n .deleteFrom(\"OperationUserPermission\")\n .where(\"documentId\", \"=\", documentId)\n .where(\"operationType\", \"=\", operationType)\n .where(\"userAddress\", \"=\", userAddress.toLowerCase())\n .execute();\n }\n\n /**\n * Get all users with permission to execute an operation\n */\n async getOperationUserPermissions(\n documentId: string,\n operationType: string,\n ): Promise<OperationUserPermissionEntry[]> {\n return this.db\n .selectFrom(\"OperationUserPermission\")\n .select([\n \"documentId\",\n \"operationType\",\n \"userAddress\",\n \"grantedBy\",\n \"createdAt\",\n ])\n .where(\"documentId\", \"=\", documentId)\n .where(\"operationType\", \"=\", operationType)\n .execute();\n }\n\n /**\n * Whether an operation-permission row exists for the user on this operation.\n */\n async hasOperationGrant(\n documentId: string,\n operationType: string,\n userAddress: string,\n ): Promise<boolean> {\n const normalizedAddress = userAddress.toLowerCase();\n\n const userPermission = await this.db\n .selectFrom(\"OperationUserPermission\")\n .select(\"userAddress\")\n .where(\"documentId\", \"=\", documentId)\n .where(\"operationType\", \"=\", operationType)\n .where(\"userAddress\", \"=\", normalizedAddress)\n .executeTakeFirst();\n\n return !!userPermission;\n }\n\n /**\n * Check if an operation has any permissions set (is restricted)\n */\n async isOperationRestricted(\n documentId: string,\n operationType: string,\n ): Promise<boolean> {\n const userPermCount = await this.db\n .selectFrom(\"OperationUserPermission\")\n .select(sql<number>`count(*)`.as(\"count\"))\n .where(\"documentId\", \"=\", documentId)\n .where(\"operationType\", \"=\", operationType)\n .executeTakeFirst();\n\n return userPermCount !== undefined && Number(userPermCount.count) > 0;\n }\n\n // ============================================\n // Document Protection\n // ============================================\n\n /**\n * Check if a specific document has a protection row set to true.\n * Falls back to `config.defaultProtection` if no row exists.\n */\n async isDocumentProtected(documentId: string): Promise<boolean> {\n const row = await this.db\n .selectFrom(\"DocumentProtection\")\n .select(\"protected\")\n .where(\"documentId\", \"=\", documentId)\n .executeTakeFirst();\n\n if (row === undefined) {\n return this.config.defaultProtection;\n }\n\n return row.protected;\n }\n\n /**\n * Walk the parent chain: if the document itself or any ancestor is protected, return true.\n * Collects all ancestor IDs first (with cycle detection), then batch-checks protection.\n */\n async isProtectedWithAncestors(\n documentId: string,\n getParentIds: GetParentIdsFn,\n ): Promise<boolean> {\n // Collect all IDs in the hierarchy (document + all ancestors)\n const allIds = await this.collectAncestorIds(documentId, getParentIds);\n\n // Batch-check protection for all IDs at once\n if (allIds.length === 0) {\n return this.config.defaultProtection;\n }\n\n const rows = await this.db\n .selectFrom(\"DocumentProtection\")\n .select([\"documentId\", \"protected\"])\n .where(\"documentId\", \"in\", allIds)\n .execute();\n\n const protectionMap = new Map(rows.map((r) => [r.documentId, r.protected]));\n\n for (const id of allIds) {\n const isProtected = protectionMap.get(id);\n // If no row exists, fall back to defaultProtection\n if (isProtected ?? this.config.defaultProtection) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Collect all ancestor IDs (including the document itself) with cycle detection.\n */\n private async collectAncestorIds(\n documentId: string,\n getParentIds: GetParentIdsFn,\n ): Promise<string[]> {\n const visited = new Set<string>();\n const queue = [documentId];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n if (visited.has(current)) continue;\n visited.add(current);\n\n const parentIds = await getParentIds(current);\n for (const parentId of parentIds) {\n if (!visited.has(parentId)) {\n queue.push(parentId);\n }\n }\n }\n\n return Array.from(visited);\n }\n\n /**\n * Upsert protection status for a document.\n */\n async setDocumentProtection(\n documentId: string,\n isProtected: boolean,\n ): Promise<void> {\n const now = new Date();\n\n await this.db\n .insertInto(\"DocumentProtection\")\n .values({\n documentId,\n protected: isProtected,\n ownerAddress: null,\n createdAt: now,\n updatedAt: now,\n })\n .onConflict((oc) =>\n oc.column(\"documentId\").doUpdateSet({\n protected: isProtected,\n updatedAt: now,\n }),\n )\n .execute();\n }\n\n /**\n * Get the owner address for a document, or null if not set.\n */\n async getDocumentOwner(documentId: string): Promise<string | null> {\n const row = await this.db\n .selectFrom(\"DocumentProtection\")\n .select(\"ownerAddress\")\n .where(\"documentId\", \"=\", documentId)\n .executeTakeFirst();\n\n return row?.ownerAddress ?? null;\n }\n\n /**\n * Upsert owner address for a document.\n */\n async setDocumentOwner(\n documentId: string,\n ownerAddress: string,\n ): Promise<void> {\n const now = new Date();\n const normalizedAddress = ownerAddress.toLowerCase();\n\n await this.db\n .insertInto(\"DocumentProtection\")\n .values({\n documentId,\n protected: this.config.defaultProtection,\n ownerAddress: normalizedAddress,\n createdAt: now,\n updatedAt: now,\n })\n .onConflict((oc) =>\n oc.column(\"documentId\").doUpdateSet({\n ownerAddress: normalizedAddress,\n updatedAt: now,\n }),\n )\n .execute();\n }\n\n /**\n * Initialize protection for a newly created document.\n * Sets protection status and grants ADMIN to the owner.\n */\n async initializeDocumentProtection(\n documentId: string,\n ownerAddress: string,\n defaultProtection?: boolean,\n ): Promise<void> {\n const now = new Date();\n const normalizedAddress = ownerAddress.toLowerCase();\n const isProtected = defaultProtection ?? this.config.defaultProtection;\n\n await this.db\n .insertInto(\"DocumentProtection\")\n .values({\n documentId,\n protected: isProtected,\n ownerAddress: normalizedAddress,\n createdAt: now,\n updatedAt: now,\n })\n .onConflict((oc) =>\n oc.column(\"documentId\").doUpdateSet({\n ownerAddress: normalizedAddress,\n updatedAt: now,\n }),\n )\n .execute();\n\n // Grant ADMIN permission to the owner\n await this.grantPermission(\n documentId,\n normalizedAddress,\n \"ADMIN\",\n normalizedAddress,\n );\n }\n\n /**\n * Get the full protection info for a document.\n */\n async getDocumentProtection(documentId: string): Promise<{\n documentId: string;\n protected: boolean;\n ownerAddress: string | null;\n }> {\n const row = await this.db\n .selectFrom(\"DocumentProtection\")\n .select([\"documentId\", \"protected\", \"ownerAddress\"])\n .where(\"documentId\", \"=\", documentId)\n .executeTakeFirst();\n\n if (!row) {\n return {\n documentId,\n protected: this.config.defaultProtection,\n ownerAddress: null,\n };\n }\n\n return row;\n }\n}\n","import type { IReactorClient } from \"@powerhousedao/reactor\";\nimport type { GetParentIdsFn } from \"./document-permission.service.js\";\n\n/**\n * The canonical parent-document resolver used for permission inheritance:\n * a document's parents are the sources of its incoming \"child\"\n * relationships. Lookup failures resolve to \"no parents\" so a relationship\n * store outage degrades to no inherited permissions rather than an error.\n */\nexport function createGetParentIdsFn(\n reactorClient: IReactorClient,\n): GetParentIdsFn {\n return async (documentId: string): Promise<string[]> => {\n try {\n const result = await reactorClient.getIncomingRelationships(\n documentId,\n \"child\",\n );\n return result.results.map((doc) => doc.header.id);\n } catch {\n return [];\n }\n };\n}\n","import type { McpRequestAuthorizer } from \"@powerhousedao/reactor-mcp\";\nimport type { AuthService } from \"./auth.service.js\";\nimport {\n AuthorizationPolicy,\n type IAuthorizationService,\n} from \"./authorization.service.js\";\n\n/**\n * Authorization gate for the /mcp endpoint (AUTH_REVIEW S-C1). MCP tools have\n * unrestricted reactor access, so access is limited to supreme admins when\n * auth is enabled. OPEN policy is public; any other policy without an\n * AuthService fails closed. The tools read as the caller: anonymous under OPEN,\n * else the admin's address and the app key its token carries.\n */\nexport function createMcpRequestAuthorizer(\n authService: AuthService | undefined,\n authorizationService: IAuthorizationService,\n): McpRequestAuthorizer {\n return async (req) => {\n if (!authService) {\n if (authorizationService.config.policy === AuthorizationPolicy.OPEN) {\n return { authorized: true, subject: {} };\n }\n return {\n authorized: false,\n status: 401,\n message: \"Authentication required\",\n };\n }\n\n const context = await authService.verifyBearer(req.headers.authorization);\n if (context instanceof Response) {\n return {\n authorized: false,\n status: context.status,\n message: \"Authentication failed\",\n };\n }\n if (!context.user) {\n return {\n authorized: false,\n status: 401,\n message: \"Authentication required\",\n };\n }\n if (!authorizationService.isSupremeAdmin(context.user.address)) {\n return {\n authorized: false,\n status: 403,\n message: \"Forbidden: MCP access requires an administrator\",\n };\n }\n return {\n authorized: true,\n subject: { address: context.user.address, key: context.user.appKey },\n };\n };\n}\n","import type { InProcessReactorModule } from \"@powerhousedao/reactor\";\nimport {\n BareReadGate,\n ModelReadGate,\n readDecisionModel,\n SyncScopeGate,\n} from \"@powerhousedao/reactor\";\nimport type { ILogger } from \"document-model\";\nimport type { AuthorizationConfig } from \"./authorization.service.js\";\n\n/**\n * The gate sync serving evaluates a document's own policy through, deciding\n * what the reactor client's read gate decides at the same flag level.\n *\n * Under `authEnforcement` it is built here rather than taken off the client\n * because it also carries the host's closes-by-default setting, which withholds\n * the domain scopes of a document nobody has policied yet. That answer belongs\n * to serving alone -- replay must keep reading an uninitialized document in\n * full -- so the two gates are separate objects over the same model.\n *\n * Below it the registered model ignores the auth scope, so the client reads\n * through the policy alone, and so does serving: a policy written below the\n * flag still withholds, where serving ungated would sync to a peer what `get`\n * refuses it.\n */\nexport function buildSyncServingGate(\n reactorModule: InProcessReactorModule | undefined,\n authorizationConfig: AuthorizationConfig,\n logger: ILogger,\n): SyncScopeGate | undefined {\n if (!reactorModule) {\n return undefined;\n }\n\n const model = readDecisionModel(\n reactorModule.featureFlags,\n reactorModule.documentModelRegistry,\n );\n if (!model) {\n return new SyncScopeGate(\n new BareReadGate(),\n reactorModule.documentView,\n logger,\n );\n }\n\n return new SyncScopeGate(\n new ModelReadGate(\n model,\n reactorModule.documentView,\n reactorModule.featureFlags.authGroups,\n reactorModule.operationIndex,\n logger,\n { withholdUninitialized: authorizationConfig.defaultProtection },\n ),\n reactorModule.documentView,\n logger,\n );\n}\n","import type { PHReactorRenown } from \"@powerhousedao/shared/clis\";\nimport type { ILogger } from \"document-model\";\n\n/** Where the credential check reads from: a remote Renown or Switchboard\n * instance, or this switchboard's own renown read model. */\nexport type RenownSource = NonNullable<PHReactorRenown[\"source\"]>;\n\n/** The `auth.renown` config block: which Renown instance to authenticate\n * against, before env overrides are applied. */\nexport type RenownConfig = PHReactorRenown;\n\n/** Resolved renown coordinates. `url` also drives this reactor's own identity,\n * so it stays meaningful when `source` is \"self\". */\nexport type ResolvedRenownConfig = {\n source: RenownSource;\n url: string | undefined;\n switchboardUrl: string | undefined;\n};\n\n/** Reading credentials from this reactor's own read model needs a host-supplied\n * verifier: core has no idea which subgraph serves that read model. */\nexport function assertCredentialVerifierForSource(\n source: RenownSource,\n hasVerifier: boolean,\n): void {\n if (source !== \"self\" || hasVerifier) {\n return;\n }\n throw new Error(\n 'Renown credential verification is set to \"self\" (auth.renown.source or ' +\n \"RENOWN_SOURCE) but no verifyCredential was provided. A host that reads \" +\n \"its own read model must pass one — see apps/switchboard, which builds \" +\n \"it from @renown/sdk createLocalCredentialVerifier — or set \" +\n \"RENOWN_SOURCE=remote to verify against a Renown instance.\",\n );\n}\n\n// Treat a blank env var as unset so `RENOWN_URL=` cannot blank out the config.\nfunction envOverride(value: string | undefined): string | undefined {\n const trimmed = value?.trim();\n return trimmed ? trimmed : undefined;\n}\n\n/** Resolve `auth.renown`; RENOWN_SOURCE / RENOWN_URL / SWITCHBOARD_URL win\n * over the config file, which wins over the SDK defaults. */\nexport function resolveRenownConfig(\n configured: RenownConfig | undefined,\n env: NodeJS.ProcessEnv,\n logger: ILogger,\n): ResolvedRenownConfig {\n return {\n source: resolveRenownSource(\n envOverride(env.RENOWN_SOURCE) ?? configured?.source,\n logger,\n ),\n url: envOverride(env.RENOWN_URL) ?? configured?.url,\n switchboardUrl:\n envOverride(env.SWITCHBOARD_URL) ?? configured?.switchboardUrl,\n };\n}\n\n// `null` is reachable despite the types: it is what `\"source\": null` in the\n// config file deserialises to, and counts as unset like a blank env var.\nfunction resolveRenownSource(\n value: string | null | undefined,\n logger: ILogger,\n): RenownSource {\n if (value === undefined || value === null) {\n return \"remote\";\n }\n if (value === \"self\" || value === \"remote\") {\n return value;\n }\n logger.warn(\n `Ignoring invalid renown source \"${value}\" (expected \"self\" or \"remote\") — using \"remote\"`,\n );\n return \"remote\";\n}\n","import { PGlite } from \"@electric-sql/pglite\";\nimport type { PGlite as PGliteType } from \"@electric-sql/pglite\";\nimport { AtomicNodeFs } from \"@powerhousedao/pglite-fs\";\nimport type { Knex } from \"knex\";\nimport knex from \"knex\";\nimport ClientPgLite from \"knex-pglite\";\nimport { type Generated, Kysely } from \"kysely\";\nimport { KyselyKnexDialect, PGColdDialect } from \"kysely-knex\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * Permission levels for documents:\n * - READ: Can fetch and read the document\n * - WRITE: Can push updates and modify the document\n * - ADMIN: Can manage document permissions and settings\n */\nexport type DocumentPermissionLevel = \"READ\" | \"WRITE\" | \"ADMIN\";\n\n/**\n * Database schema for document permissions\n */\nexport interface DocumentProtectionTable {\n documentId: string;\n protected: boolean;\n ownerAddress: string | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface DocumentPermissionDatabase {\n DocumentPermission: DocumentPermissionTable;\n OperationUserPermission: OperationUserPermissionTable;\n DocumentProtection: DocumentProtectionTable;\n}\n\nexport interface DocumentPermissionTable {\n id: Generated<number>;\n documentId: string;\n userAddress: string;\n permission: DocumentPermissionLevel;\n grantedBy: string;\n createdAt: Date;\n updatedAt: Date;\n}\n\n// Operation permission tables\nexport interface OperationUserPermissionTable {\n id: Generated<number>;\n documentId: string;\n operationType: string;\n userAddress: string;\n grantedBy: string;\n createdAt: Date;\n}\n\ntype Db = Kysely<any>;\n\n// PGlite parses `timestamp` (no tz) columns as local time; read-model columns\n// store UTC, so parse them as UTC or values shift by the host's TZ offset.\nexport const PGLITE_UTC_PARSERS = {\n // 1114 = timestamp without time zone\n 1114: (value: string) => new Date(`${value.replace(\" \", \"T\")}Z`),\n} as const;\n\nfunction isPG(connectionString: string) {\n if (\n connectionString.startsWith(\"postgresql://\") ||\n connectionString.startsWith(\"postgres://\")\n ) {\n return true;\n }\n return false;\n}\n\n/**\n * Optional factory used by callers (e.g. Switchboard) to inject a\n * version-specific PGLite instance — e.g. `pglite-legacy-02` when an existing\n * data dir was created with an older PG major. Wire-compatible with the\n * current PGLite class for the surface knex-pglite uses.\n */\nexport type PgliteFactory = (\n connectionString: string | undefined,\n) => PGliteType;\n\nexport interface DbClient {\n db: Db;\n knex: Knex;\n pglite: PGliteType | undefined;\n}\n\n/**\n * Cache of DB clients keyed by connection string. Reactor-api's read-model\n * layer wires analytics, attachments, and document-permissions as separate\n * consumers but they all target the same logical database (one postgres\n * instance, many schemas). Without caching:\n * - PGlite: two `new PGlite(samePath)` calls mean two embedded postgres\n * processes contending for the same data dir, racing shutdown syncs\n * and silently losing writes — a correctness bug.\n * - Postgres: each consumer opens an independent pool against the same\n * backend — wasteful but correct.\n * Caching by connection string returns the same knex/PGlite pair to every\n * consumer so writes coexist in one MemoryFS and one atomic snapshot, and\n * postgres callers get connection-pool dedup for free.\n *\n * Entries are evicted from inside the wrapped `knex.destroy()` below, so a\n * teardown + re-init in the same process (tests, hot-reloads) constructs\n * a fresh client instead of returning a closed pool.\n */\nconst IN_MEMORY_CACHE_KEY = Symbol(\"getDbClient:in-memory\");\ntype CacheKey = string | typeof IN_MEMORY_CACHE_KEY;\nconst dbClientCache = new Map<CacheKey, DbClient>();\n\nexport function getDbClient(\n connectionString: string | undefined = undefined,\n pgliteFactory?: PgliteFactory,\n): DbClient {\n const cacheKey: CacheKey = connectionString ?? IN_MEMORY_CACHE_KEY;\n const cached = dbClientCache.get(cacheKey);\n if (cached) return cached;\n\n const isPg = connectionString && isPG(connectionString);\n const client = isPg ? \"pg\" : (ClientPgLite as typeof knex.Client);\n const pgliteInstance: PGliteType | undefined = isPg\n ? undefined\n : pgliteFactory\n ? pgliteFactory(connectionString)\n : connectionString\n ? new PGlite({\n fs: new AtomicNodeFs(connectionString),\n parsers: PGLITE_UTC_PARSERS,\n })\n : new PGlite({ parsers: PGLITE_UTC_PARSERS });\n const connection = isPg ? { connectionString } : { pglite: pgliteInstance };\n\n // If path is not postgres then it is a filesystem path.\n // Ensures parent directory is created.\n if (connectionString && !isPg) {\n const dirPath = path.resolve(connectionString, \"..\");\n if (!fs.existsSync(dirPath)) {\n fs.mkdirSync(dirPath, { recursive: true });\n }\n }\n\n const knexInstance = knex({\n client,\n connection,\n });\n\n const kyselyInstance = new Kysely({\n dialect: new KyselyKnexDialect({\n knex: knexInstance,\n kyselySubDialect: new PGColdDialect(),\n }),\n });\n\n const dbClient: DbClient = {\n db: kyselyInstance,\n knex: knexInstance,\n pglite: pgliteInstance,\n };\n\n // Wrap knex.destroy so closing the client also drops the cache entry.\n // Works for both PGlite (which has a `closed` flag) and raw Postgres\n // pools (which don't), and keeps the Map from accumulating dead entries\n // when callers cycle through many distinct paths. `destroy` lives on\n // the Knex prototype as a read-only method, so use defineProperty to\n // shadow it on this instance.\n const originalDestroy = knexInstance.destroy.bind(knexInstance);\n Object.defineProperty(knexInstance, \"destroy\", {\n configurable: true,\n writable: true,\n value: async (...args: unknown[]) => {\n if (dbClientCache.get(cacheKey) === dbClient) {\n dbClientCache.delete(cacheKey);\n }\n return originalDestroy(...(args as []));\n },\n });\n\n dbClientCache.set(cacheKey, dbClient);\n return dbClient;\n}\n\nexport const initAnalyticsStoreSql = [\n `create table if not exists \"AnalyticsSeries\"\n (\n id serial primary key,\n source varchar(255) not null,\n start timestamp not null,\n \"end\" timestamp,\n metric varchar(255) not null,\n value real not null,\n unit varchar(255),\n fn varchar(255) not null,\n params json\n );`,\n `create unique index if not exists \"AnalyticsSeries_pkey\"\n on \"AnalyticsSeries\" (id);`,\n `create index if not exists analyticsseries_end_index\n on \"AnalyticsSeries\" (\"end\");`,\n `create index if not exists analyticsseries_fn_index\n on \"AnalyticsSeries\" (fn);`,\n `create index if not exists analyticsseries_metric_index\n on \"AnalyticsSeries\" (metric);`,\n `create index if not exists analyticsseries_source_index\n on \"AnalyticsSeries\" (source);`,\n `create index if not exists analyticsseries_start_index\n on \"AnalyticsSeries\" (start);`,\n `create index if not exists analyticsseries_unit_index\n on \"AnalyticsSeries\" (unit);`,\n `create index if not exists analyticsseries_value_index\n on \"AnalyticsSeries\" (value);`,\n `create table if not exists \"AnalyticsDimension\"\n (\n id serial primary key,\n dimension varchar(255) not null,\n path varchar(255) not null,\n label varchar(255),\n icon varchar(1000),\n description text\n );`,\n `create unique index if not exists \"AnalyticsDimension_pkey\"\n on \"AnalyticsDimension\" (id);`,\n `create index if not exists analyticsdimension_dimension_index\n on \"AnalyticsDimension\" (dimension);`,\n `create index if not exists analyticsdimension_path_index\n on \"AnalyticsDimension\" (path);`,\n `create table if not exists \"AnalyticsSeries_AnalyticsDimension\"\n (\n \"seriesId\" integer not null\n constraint analyticsseries_analyticsdimension_seriesid_foreign\n references \"AnalyticsSeries\"\n on delete cascade,\n \"dimensionId\" integer not null\n constraint analyticsseries_analyticsdimension_dimensionid_foreign\n references \"AnalyticsDimension\"\n on delete cascade\n );`,\n `create index if not exists analyticsseries_analyticsdimension_dimensionid_index\n on \"AnalyticsSeries_AnalyticsDimension\" (\"dimensionId\");`,\n `create index if not exists analyticsseries_analyticsdimension_seriesid_index\n on \"AnalyticsSeries_AnalyticsDimension\" (\"seriesId\");`,\n];\n","import type { PGlite } from \"@electric-sql/pglite\";\nimport type { IAnalyticsStore } from \"@powerhousedao/analytics-engine-core\";\nimport { PostgresAnalyticsStore } from \"@powerhousedao/analytics-engine-pg\";\nimport { getConfig } from \"@powerhousedao/config/node\";\nimport type {\n IDocumentModelRegistry,\n IDriveClient,\n IReadModel,\n IReactorClient,\n InProcessReactorModule,\n IProcessorManager as IReactorProcessorManager,\n ISyncManager,\n InProcessReactorClientModule,\n ProcessorRecord as ReactorProcessorRecord,\n} from \"@powerhousedao/reactor\";\nimport type { SyncScopeGate } from \"@powerhousedao/reactor\";\nimport {\n AttachmentBuilder,\n AttachmentReferenceIndexBuilder,\n} from \"@powerhousedao/reactor-attachments\";\nimport type {\n AttachmentBuildResult,\n AttachmentDatabase,\n AttachmentReferenceIndexBuildResult,\n IAttachmentReferenceWriter,\n} from \"@powerhousedao/reactor-attachments\";\nimport { createAttachmentClient } from \"@powerhousedao/reactor-attachments/client\";\nimport { setupMcpServer } from \"@powerhousedao/reactor-mcp\";\nimport type {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport type { Kysely } from \"kysely\";\nimport { mkdir } from \"node:fs/promises\";\nimport type http from \"node:http\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport type { Pool } from \"pg\";\nimport { WebSocketServer } from \"ws\";\nimport { createReactorHostModuleBase } from \"@powerhousedao/reactor\";\nimport {\n createRelationalDb,\n type IRelationalDb,\n type ProcessorApp,\n type ProcessorFactory,\n} from \"@powerhousedao/shared/processors\";\nimport { childLogger, type ILogger } from \"document-model\";\nimport { config, DefaultCoreSubgraphs } from \"./config.js\";\nimport { createStartupAttachmentBackend } from \"./attachment-backend.js\";\nimport {\n AttachmentAccessService,\n type AttachmentReferenceProjectionCapability,\n type IAttachmentAccessService,\n} from \"./services/attachment-access.service.js\";\nimport { createCanonicalDocumentIdResolver } from \"./services/canonical-document-id.js\";\nimport { AuthSubgraph } from \"./graphql/auth/subgraph.js\";\nimport {\n createAuthFetchMiddleware,\n type AuthFetchMiddleware,\n} from \"./graphql/gateway/auth-middleware.js\";\nimport {\n createGatewayAdapter,\n createHttpAdapter,\n type GatewayAdapterType,\n} from \"./graphql/gateway/factory.js\";\nimport {\n createRequireAuthFetchMiddleware,\n type RequireAuthFetchMiddleware,\n} from \"./graphql/gateway/require-auth-middleware.js\";\nimport type { IHttpAdapter, TlsOptions } from \"./graphql/gateway/types.js\";\nimport { GraphQLManager } from \"./graphql/graphql-manager.js\";\nimport {\n CORE_PACKAGE_NAME,\n HttpRouteService,\n RelationalWebhookStore,\n WEBHOOK_SEGMENT,\n WebhookService,\n} from \"./http/index.js\";\nimport {\n decodeExplorerUrlState,\n renderGraphqlPlayground,\n} from \"./graphql/playground.js\";\nimport { ReactorSubgraph } from \"./graphql/reactor/subgraph.js\";\nimport type { SubgraphClass } from \"./graphql/types.js\";\nimport { runMigrations } from \"./migrations/index.js\";\nimport { ImportPackageLoader } from \"./packages/import-loader.js\";\nimport {\n getUniqueDocumentModels,\n PackageManager,\n} from \"./packages/package-manager.js\";\nimport {\n AuthService,\n type CredentialVerifier,\n} from \"./services/auth.service.js\";\nimport { createRenownCredentialVerifier } from \"./services/renown-credential-verifier.js\";\nimport type {\n AuthorizationConfig,\n IAuthorizationService,\n} from \"./services/authorization.service.js\";\nimport {\n AuthorizationPolicy,\n createAuthorizationService,\n} from \"./services/authorization.service.js\";\nimport { DocumentPermissionService } from \"./services/document-permission.service.js\";\nimport { createGetParentIdsFn } from \"./services/get-parent-ids.js\";\nimport { createMcpRequestAuthorizer } from \"./services/mcp-request-authorizer.js\";\nimport { buildSyncServingGate } from \"./services/sync-serving-gate.js\";\nimport {\n assertCredentialVerifierForSource,\n resolveRenownConfig,\n type RenownConfig,\n type ResolvedRenownConfig,\n} from \"./services/renown-config.js\";\nimport type {\n API,\n IPackageLoader,\n IProcessorHostModule,\n Processor,\n ProcessorFactoryBuilder,\n ReadinessGate,\n} from \"./types.js\";\nimport {\n getDbClient,\n initAnalyticsStoreSql,\n type DocumentPermissionDatabase,\n type PgliteFactory,\n} from \"./utils/db.js\";\n\nconst defaultLogger = childLogger([\"reactor-api\", \"server\"]);\n\ntype Options = {\n port?: number;\n dbPath: string | undefined;\n client?: PGlite | typeof Pool | undefined;\n /**\n * Factory for the PGLite instance backing the read-model store. When set,\n * `getDbClient` uses it instead of constructing `new PGlite(dbPath)`. Used\n * by Switchboard to keep a legacy-version data dir readable while running\n * the newer Switchboard binary.\n */\n pgliteFactory?: PgliteFactory;\n configFile?: string;\n packages?: string[];\n auth?: {\n enabled: boolean;\n admins: string[];\n /** Read the bearer and populate `ctx.user` independently of `enabled`.\n * Defaults to `enabled`; `RESOLVE_CALLER_IDENTITY` overrides either. */\n resolveIdentity?: boolean;\n /** Reject anonymous callers with a 401 before any subgraph sees the\n * request. Off by default; `REQUIRE_AUTHENTICATED_CALLER` overrides.\n * Requires identity resolution to be on — refused at boot without it. */\n requireAuthenticatedCaller?: boolean;\n /** Mounted paths that stay reachable anonymously while\n * `requireAuthenticatedCaller` is on, for a flow that runs before\n * sign-in. Matched against the request's pathname in full, never as a\n * prefix. `REQUIRE_AUTHENTICATED_CALLER_EXEMPT_PATHS` overrides, as a\n * comma-separated list. Each entry is a hole in the floor: only ever name\n * a path serving operations that are safe without a caller. */\n requireAuthenticatedCallerExemptPaths?: string[];\n /** Decide an attachment read with the referencing document's own policy\n * instead of the host permission tables. Off by default;\n * `ATTACHMENT_READS_FOLLOW_DOCUMENT_POLICY` overrides. Requires auth\n * enforcement, which is what supplies the model — refused at boot\n * without it. */\n attachmentReadsFollowDocumentPolicy?: boolean;\n };\n /** Renown coordinates the host already resolved, used verbatim instead of\n * resolving `auth.renown` and the env again (which would warn twice). */\n renown?: ResolvedRenownConfig;\n /** Credential check replacing the built-in remote Renown one; required when\n * the resolved source is \"self\" (see assertCredentialVerifierForSource). */\n verifyCredential?: CredentialVerifier;\n https?:\n | {\n keyPath: string;\n certPath: string;\n }\n | boolean\n | undefined;\n packageLoaders?: IPackageLoader[];\n processors?: Record<string, ProcessorInitializer[]>;\n mcp?: boolean;\n processorConfig?: Map<string, unknown>;\n /**\n * Document permission service instance.\n * When provided, the Auth subgraph is registered and document permission\n * checks are enforced on document operations.\n * If not provided, can be auto-created by setting DOCUMENT_PERMISSIONS_ENABLED=true\n * environment variable.\n */\n documentPermissionService?: DocumentPermissionService;\n enableDocumentModelSubgraphs?: boolean;\n logger?: ILogger;\n /**\n * Filesystem path for attachment binary storage.\n * Defaults to a sibling \"attachments\" directory next to dbPath,\n * or os.tmpdir() for in-memory DB deployments.\n */\n attachmentStoragePath?: string;\n};\n\ntype ProcessorInitializer = ProcessorFactoryBuilder;\n\nconst DEFAULT_PORT = 4000;\n\n/**\n * Doc-perms require auth: with auth off no `user` is ever resolved, so every\n * authorization check fails closed. Refuse to boot rather than run broken.\n */\nexport function assertAuthRequiredForDocumentPermissions(\n authEnabled: boolean,\n documentPermissionsRequested: boolean,\n): void {\n if (!authEnabled && documentPermissionsRequested) {\n throw new Error(\n \"Document permissions require authentication: AUTH_ENABLED is false but \" +\n \"document permissions were requested (DOCUMENT_PERMISSIONS_ENABLED=true \" +\n \"or a documentPermissionService was provided). Enable authentication \" +\n \"(AUTH_ENABLED=true, or auth.enabled in the config file) or disable \" +\n \"document permissions.\",\n );\n }\n}\n\n/**\n * Refuses SKIP_CREDENTIAL_VERIFICATION at boot outside tests or an explicit\n * opt-in: it removes the only binding between a token's claimed address and its\n * signing key. Fail-closed — unset NODE_ENV counts as production.\n */\nexport function assertSkipCredentialVerificationAllowed(\n resolvesCallerIdentity: boolean,\n skipCredentialVerification: boolean,\n env: NodeJS.ProcessEnv,\n): void {\n if (!resolvesCallerIdentity || !skipCredentialVerification) {\n return;\n }\n const inAutomatedTest = env.VITEST === \"true\" || env.NODE_ENV === \"test\";\n const acknowledged =\n env.ALLOW_INSECURE_SKIP_CREDENTIAL_VERIFICATION === \"true\";\n if (!inAutomatedTest && !acknowledged) {\n throw new Error(\n \"SKIP_CREDENTIAL_VERIFICATION is set but refused: it disables the live \" +\n \"Renown credential check — the only check binding a token's claimed \" +\n \"address to the key that signed it — so honoring it allows identity \" +\n \"spoofing, including of admins. It is never safe in production. For \" +\n \"local or sandbox use, also set \" +\n \"ALLOW_INSECURE_SKIP_CREDENTIAL_VERIFICATION=true to acknowledge the \" +\n \"risk; automated test runs (VITEST=true or NODE_ENV=test) are exempt.\",\n );\n }\n}\n\n/**\n * Requiring an authenticated caller requires identity resolution to exist at\n * all: with neither AUTH_ENABLED nor RESOLVE_CALLER_IDENTITY the middleware\n * never reads a bearer, no `user` is ever resolved, and the\n * require-authenticated-caller middleware would reject every caller —\n * authenticated ones included. Refuse to boot rather than run broken.\n */\nexport function assertRequireAuthenticatedCallerAllowed(\n requireAuthenticatedCaller: boolean,\n resolvesCallerIdentity: boolean,\n exemptPaths: readonly string[] = [],\n): void {\n /**\n * An exemption is only ever a hole in this floor, so configuring one while\n * the floor is off is not a harmless no-op: it reads, to anyone auditing the\n * configuration, as a surface that was deliberately opened — and therefore\n * as a floor that exists. Refuse rather than let the two drift.\n */\n if (!requireAuthenticatedCaller && exemptPaths.length > 0) {\n throw new Error(\n \"REQUIRE_AUTHENTICATED_CALLER_EXEMPT_PATHS is set but refused: \" +\n \"REQUIRE_AUTHENTICATED_CALLER is off, so nothing is being exempted \" +\n \"from anything and the configuration claims a protection the server \" +\n \"is not applying. Enable the floor, or drop the exemptions.\",\n );\n }\n\n /**\n * A path that cannot match anything is worse than no path: the operator\n * believes the flow is reachable, and finds out when the first user cannot\n * claim an invitation. `URL.pathname` is always absolute, so an entry that\n * does not start with `/` never matches, whatever the router does.\n */\n const relative = exemptPaths.filter((path) => !path.trim().startsWith(\"/\"));\n if (relative.length > 0) {\n throw new Error(\n `REQUIRE_AUTHENTICATED_CALLER_EXEMPT_PATHS contains ${relative\n .map((path) => `\"${path}\"`)\n .join(\", \")}, which cannot match: an exempt path is compared against ` +\n \"the request's pathname and must start with '/' (for example \" +\n \"'/graphql/public').\",\n );\n }\n\n if (!requireAuthenticatedCaller || resolvesCallerIdentity) {\n return;\n }\n throw new Error(\n \"REQUIRE_AUTHENTICATED_CALLER is set but refused: it rejects every \" +\n \"request without a resolved caller, and with neither AUTH_ENABLED nor \" +\n \"RESOLVE_CALLER_IDENTITY the server never reads a bearer, so it would \" +\n \"reject every caller, including authenticated ones. Enable identity \" +\n \"resolution first (RESOLVE_CALLER_IDENTITY=true or AUTH_ENABLED=true).\",\n );\n}\n\n/**\n * Deciding an attachment read by the document's policy needs a policy model to\n * decide with, and that is what auth enforcement supplies. Without one there is\n * nothing to consult, so the setting would silently leave the permission tables\n * in charge — configuration that describes a protection the server is not\n * applying, which is worse than no configuration at all. Refuse instead.\n */\nexport function assertAttachmentPolicyReadsAllowed(\n attachmentReadsFollowDocumentPolicy: boolean,\n hasDecisionModel: boolean,\n): void {\n if (!attachmentReadsFollowDocumentPolicy || hasDecisionModel) {\n return;\n }\n throw new Error(\n \"ATTACHMENT_READS_FOLLOW_DOCUMENT_POLICY is set but refused: deciding an \" +\n \"attachment read by the referencing document's policy requires a policy \" +\n \"model to evaluate, and this composition has none, so the host \" +\n \"permission tables would keep deciding while the configuration says \" +\n \"otherwise. Enable auth enforcement first (REACTOR_AUTH_ENFORCEMENT=true).\",\n );\n}\n\nfunction createReadinessGate(): ReadinessGate {\n let ready = false;\n return {\n isReady: () => ready,\n markReady: () => {\n ready = true;\n },\n };\n}\n\n/**\n * The GraphiQL explorer page's mount prefix. `path.posix.join` normalizes the\n * join with `basePath` — a naive template literal would produce `//explorer`\n * for the default `/` basePath, which express compiles into a route that only\n * matches `//explorer`, leaving `GET /explorer` a 404.\n */\nexport function getExplorerPrefix(basePath: string): string {\n return path.posix.join(basePath, \"explorer\");\n}\n\nfunction resolveAttachmentStoragePath(options: Options): string {\n if (options.attachmentStoragePath) return options.attachmentStoragePath;\n if (options.dbPath && !options.dbPath.startsWith(\"postgres\")) {\n return path.resolve(options.dbPath, \"..\", \"attachments\");\n }\n return path.join(tmpdir(), \"reactor-attachments\");\n}\n\n/**\n * Initializes the database and analytics store. The returned `closers` are\n * idempotent thunks that release the underlying knex pool and PGlite instance\n * (when on-disk PGlite is in use); callers are expected to run them as part\n * of API teardown so PGlite WAL is flushed and the data-dir lock is released.\n */\nasync function initializeDatabaseAndAnalytics(\n dbPath: string | undefined,\n pgliteFactory: PgliteFactory | undefined,\n): Promise<{\n relationalDb: IRelationalDb;\n analyticsStore: IAnalyticsStore;\n closers: Array<() => Promise<void>>;\n}> {\n const { db, knex, pglite } = getDbClient(dbPath, pgliteFactory);\n const relationalDb = createRelationalDb<unknown>(db);\n const analyticsStore = new PostgresAnalyticsStore({\n knex,\n });\n\n for (const sql of initAnalyticsStoreSql) {\n await knex.raw(sql);\n }\n\n return {\n relationalDb,\n analyticsStore,\n closers: makeDbClosers(knex, pglite),\n };\n}\n\n/**\n * Builds best-effort closers for a knex/PGlite pair returned by\n * {@link getDbClient}. Order is significant: knex first releases its pool\n * (which is what the application talks to), then PGlite flushes WAL and\n * unlocks the data dir.\n */\nfunction makeDbClosers(\n knexInstance: { destroy: () => Promise<void> },\n pglite: PGlite | undefined,\n): Array<() => Promise<void>> {\n const closers: Array<() => Promise<void>> = [() => knexInstance.destroy()];\n if (pglite) {\n closers.push(async () => {\n if (!pglite.closed) await pglite.close();\n });\n }\n return closers;\n}\n\n/**\n * Resolves the gateway adapter type from the `GATEWAY_ADAPTER` env var.\n * Defaults to \"apollo\" (the federation gateway, production behavior).\n * \"stitching\" selects the in-process graphql-tools merge gateway (#1565\n * prototype); \"mercurius\" the Fastify federation gateway.\n */\nfunction resolveGatewayAdapterType(logger: ILogger): GatewayAdapterType {\n const configured = process.env.GATEWAY_ADAPTER;\n if (configured === undefined) {\n return \"apollo\";\n }\n if (\n configured === \"apollo\" ||\n configured === \"mercurius\" ||\n configured === \"stitching\"\n ) {\n return configured;\n }\n logger.warn(\n `Unknown GATEWAY_ADAPTER=\"${configured}\"; falling back to \"apollo\"`,\n );\n return \"apollo\";\n}\n\n/**\n * Sets up the subgraph manager and registers subgraphs\n */\nasync function setupGraphQLManager(\n httpAdapter: IHttpAdapter,\n authFetchMiddleware: AuthFetchMiddleware | undefined,\n requireAuthFetchMiddleware: RequireAuthFetchMiddleware | undefined,\n httpServer: http.Server,\n wsServer: WebSocketServer,\n client: IReactorClient,\n relationalDb: IRelationalDb,\n analyticsStore: IAnalyticsStore,\n syncManager: ISyncManager,\n subgraphs: {\n extended: Map<string, SubgraphClass[]>;\n core: SubgraphClass[];\n },\n logger: ILogger,\n authorizationService: IAuthorizationService,\n authService?: AuthService,\n documentPermissionService?: DocumentPermissionService,\n enableDocumentModelSubgraphs?: boolean,\n port?: number,\n reactorDriveClient?: IDriveClient,\n syncServingGate?: SyncScopeGate,\n httpRoutes?: HttpRouteService,\n): Promise<GraphQLManager> {\n const graphqlManager = new GraphQLManager(\n config.basePath,\n httpServer,\n wsServer,\n client,\n relationalDb,\n analyticsStore,\n syncManager,\n logger,\n httpAdapter,\n await createGatewayAdapter(resolveGatewayAdapterType(logger), logger),\n authService,\n documentPermissionService,\n {\n enableDocumentModelSubgraphs,\n },\n port,\n authorizationService,\n reactorDriveClient,\n syncServingGate,\n httpRoutes,\n );\n\n await graphqlManager.init(\n subgraphs.core,\n authFetchMiddleware,\n requireAuthFetchMiddleware,\n );\n\n for (const [packageName, collection] of subgraphs.extended.entries()) {\n for (const subgraph of collection) {\n await graphqlManager.registerSubgraph(\n subgraph,\n \"graphql\",\n false,\n packageName,\n );\n }\n }\n\n await graphqlManager.updateRouter();\n\n return graphqlManager;\n}\n\n/**\n * Sets up event listeners for package manager changes\n */\nfunction setupEventListeners(\n pkgManager: PackageManager,\n graphqlManager: GraphQLManager,\n reactorProcessorManager: IReactorProcessorManager,\n moduleFor: (packageName: string) => IProcessorHostModule,\n documentModelRegistry?: IDocumentModelRegistry,\n): void {\n pkgManager.onDocumentModelsChange((packagedModels) => {\n if (documentModelRegistry) {\n // Replace each incoming type's whole version family: skipping types\n // that are already registered would never pick up a new version of a\n // versioned model (or regenerated code for an existing one), and\n // unregisterModules is type-scoped so partial re-registration would\n // drop sibling versions.\n const newModules = getUniqueDocumentModels(\n Object.values(packagedModels).flat(),\n );\n const incomingTypes = new Set(\n newModules.map((m) => m.documentModel.global.id),\n );\n if (incomingTypes.size > 0) {\n documentModelRegistry.unregisterModules(...incomingTypes);\n const results = documentModelRegistry.registerModules(...newModules);\n for (const result of results) {\n if (result.status === \"success\") {\n defaultLogger.info(\n `Registered document model: ${result.item.documentModel.global.id} v${result.item.version ?? 1}`,\n );\n } else {\n defaultLogger.error(\n `Failed to register document model: ${result.error.message}`,\n );\n }\n }\n }\n\n // Manifests change together with document models (they live under the\n // same document-models/ tree), so swap them here as well.\n const manifests = pkgManager.getUniqueUpgradeManifests();\n if (manifests.length > 0) {\n documentModelRegistry.unregisterUpgradeManifests(\n ...manifests.map((m) => m.documentType),\n );\n const manifestResults = documentModelRegistry.registerUpgradeManifests(\n ...manifests,\n );\n for (const result of manifestResults) {\n if (result.status === \"error\") {\n defaultLogger.error(\n `Failed to register upgrade manifest: ${result.error.message}`,\n );\n }\n }\n }\n }\n void graphqlManager.regenerateDocumentModelSubgraphs();\n });\n\n let knownSubgraphPackages = new Set<string>();\n pkgManager.onSubgraphsChange((packagedSubgraphs) => {\n void (async () => {\n for (const [packageName, subgraphs] of packagedSubgraphs) {\n const incomingNames = new Set<string>();\n for (const subgraph of subgraphs) {\n const instance = await graphqlManager.registerSubgraph(\n subgraph,\n \"graphql\",\n false,\n packageName,\n );\n // Registration returns undefined when the subgraph is rejected\n // (e.g. its name is reserved by a core subgraph, issue #2972).\n // Nothing was mounted, so the name is not provided and must not\n // shield a stale same-named subgraph from being pruned below.\n if (!instance) {\n continue;\n }\n incomingNames.add(instance.name);\n }\n // The package is still loaded but dropped some (or all) of its\n // subgraphs: tear down the ones it no longer provides.\n await graphqlManager.prunePackageSubgraphs(packageName, incomingNames);\n }\n // A package that vanished from the map entirely (uninstalled or\n // removed from the config) keeps none of its subgraphs.\n for (const packageName of knownSubgraphPackages) {\n if (!packagedSubgraphs.has(packageName)) {\n await graphqlManager.unregisterPackage(packageName);\n }\n }\n knownSubgraphPackages = new Set(packagedSubgraphs.keys());\n await graphqlManager.updateRouter();\n })();\n });\n\n let knownProcessorPackages = new Set<string>();\n pkgManager.onProcessorsChange((processors) => {\n void (async () => {\n // Packages that vanished from the map entirely keep none of their\n // factories: unregister the leftovers.\n for (const packageName of knownProcessorPackages) {\n if (!processors.has(packageName)) {\n await reactorProcessorManager.unregisterFactory(packageName);\n }\n }\n knownProcessorPackages = new Set(processors.keys());\n\n for (const [packageName, fns] of processors) {\n await reactorProcessorManager.unregisterFactory(packageName);\n\n const factories = fns.map((fn) => fn(moduleFor(packageName)));\n\n const validBuilders = factories.filter(\n (factory): factory is ProcessorFactory =>\n typeof factory === \"function\",\n );\n\n if (!validBuilders.length) {\n continue;\n }\n\n await reactorProcessorManager.registerFactory(\n packageName,\n async (driveHeader) =>\n (\n await Promise.all(\n validBuilders.map(async (driveFactory) => {\n try {\n const result = await driveFactory(driveHeader);\n return result as unknown as ReactorProcessorRecord[];\n } catch (e) {\n const logger = defaultLogger;\n logger.error(\n `Error creating processor for drive ${driveHeader.id}:`,\n e,\n );\n return [];\n }\n }),\n )\n ).flat(),\n );\n }\n })();\n });\n}\n\n/**\n * Starts the server (HTTP or HTTPS) and attaches WebSocket server\n */\nasync function startServer(\n httpAdapter: IHttpAdapter,\n port: number,\n httpsOptions: Options[\"https\"],\n logger: ILogger,\n): Promise<{ httpServer: http.Server; wsServer: WebSocketServer }> {\n const tls: TlsOptions | undefined =\n httpsOptions === true\n ? true\n : typeof httpsOptions === \"object\"\n ? { keyPath: httpsOptions.keyPath, certPath: httpsOptions.certPath }\n : undefined;\n\n const httpServer = await httpAdapter.listen(port, tls);\n\n const wsServer = new WebSocketServer({\n server: httpServer,\n path: \"/graphql/subscriptions\",\n });\n\n logger.info(\"WebSocket server available at /graphql/subscriptions\");\n\n return { httpServer, wsServer };\n}\n\n/**\n * Private helper function that sets up common infrastructure before API initialization.\n * This includes auth configuration, database setup, and package manager initialization.\n */\nasync function _setupCommonInfrastructure(options: Options): Promise<{\n port: number;\n httpAdapter: IHttpAdapter;\n authFetchMiddleware: AuthFetchMiddleware | undefined;\n requireAuthFetchMiddleware: RequireAuthFetchMiddleware | undefined;\n authService: AuthService | undefined;\n relationalDb: IRelationalDb;\n analyticsStore: IAnalyticsStore;\n documentPermissionService: DocumentPermissionService | undefined;\n authorizationConfig: AuthorizationConfig;\n attachments: AttachmentBuildResult;\n attachmentReferenceIndex: AttachmentReferenceIndexBuildResult;\n packages: PackageManager;\n dbClosers: Array<() => Promise<void>>;\n readiness: ReadinessGate;\n httpRoutes: HttpRouteService;\n attachmentReadsFollowDocumentPolicy: boolean;\n}> {\n const port = options.port ?? DEFAULT_PORT;\n const { adapter: httpAdapter } = await createHttpAdapter(\"express\");\n const logger = options.logger ?? defaultLogger;\n\n // Setup auth configuration\n let admins: string[] = [];\n let authEnabled = false;\n let configuredResolveIdentity: boolean | undefined;\n let configuredRequireAuth: boolean | undefined;\n let configuredExemptPaths: string[] | undefined;\n let configuredAttachmentPolicyReads: boolean | undefined;\n let configuredRenown: RenownConfig | undefined;\n if (options.configFile) {\n const config = getConfig(options.configFile);\n admins = config.auth?.admins.map((a) => a.toLowerCase()) ?? [];\n authEnabled = config.auth?.enabled ?? false;\n configuredRenown = config.auth?.renown;\n } else if (options.auth) {\n admins = options.auth.admins.map((a) => a.toLowerCase());\n authEnabled = options.auth.enabled;\n configuredResolveIdentity = options.auth.resolveIdentity;\n configuredRequireAuth = options.auth.requireAuthenticatedCaller;\n configuredExemptPaths = options.auth.requireAuthenticatedCallerExemptPaths;\n configuredAttachmentPolicyReads =\n options.auth.attachmentReadsFollowDocumentPolicy;\n }\n const {\n AUTH_ENABLED,\n RESOLVE_CALLER_IDENTITY,\n REQUIRE_AUTHENTICATED_CALLER,\n REQUIRE_AUTHENTICATED_CALLER_EXEMPT_PATHS,\n ATTACHMENT_READS_FOLLOW_DOCUMENT_POLICY,\n ADMINS,\n DEFAULT_PROTECTION,\n DOCUMENT_PERMISSIONS_ENABLED,\n SKIP_CREDENTIAL_VERIFICATION,\n CREDENTIAL_VERIFICATION_CACHE_TTL_MS,\n } = process.env;\n if (AUTH_ENABLED !== undefined) {\n authEnabled = AUTH_ENABLED === \"true\";\n }\n\n /**\n * Whether the auth middleware reads the bearer and populates `ctx.user`,\n * independently of the authorization policy.\n *\n * Defaults to `authEnabled`, so a deployment that never sets it behaves\n * exactly as it did: auth on means the token is read AND the policy is\n * `ADMIN_ONLY`; auth off means neither. Setting it explicitly is what\n * separates the two — a server can then know who is calling while the policy\n * stays `OPEN`, which is the combination custom subgraphs need and the one\n * `AUTH_ENABLED` alone cannot express.\n */\n let resolveCallerIdentity = configuredResolveIdentity ?? authEnabled;\n if (RESOLVE_CALLER_IDENTITY !== undefined) {\n resolveCallerIdentity = RESOLVE_CALLER_IDENTITY === \"true\";\n }\n\n /**\n * Whether the require-authenticated-caller middleware is active: anonymous\n * callers are rejected with a 401 before any subgraph sees the request.\n *\n * Off by default, so nothing changes for existing deployments. This is the\n * enforcement half of the `RESOLVE_CALLER_IDENTITY` split: that one lets a\n * server know who is calling while the policy stays `OPEN`, and this one\n * closes the hole it leaves open — under `OPEN`, an anonymous caller\n * reaches the whole generic surface (document CRUD, sync, every custom\n * subgraph), because `OpenAuthorizationService` answers `true` to\n * everything. `ADMIN_ONLY` is the only alternative today, and it locks\n * out every non-admin; this expresses \"authenticated callers allowed,\n * anonymous not\".\n */\n let requireAuthenticatedCaller = configuredRequireAuth ?? false;\n if (REQUIRE_AUTHENTICATED_CALLER !== undefined) {\n requireAuthenticatedCaller = REQUIRE_AUTHENTICATED_CALLER === \"true\";\n }\n\n /**\n * The paths the floor above does not apply to. Comma-separated, like\n * `ADMINS`, because a deployment configures this the same way it configures\n * everything else: one variable, one line, however many values it has.\n *\n * Empty entries are dropped rather than refused, so a trailing comma or a\n * value split across lines in a manifest is not a boot failure; a value that\n * cannot ever match is refused, in\n * {@link assertRequireAuthenticatedCallerAllowed}.\n */\n let requireAuthenticatedCallerExemptPaths = configuredExemptPaths ?? [];\n if (REQUIRE_AUTHENTICATED_CALLER_EXEMPT_PATHS !== undefined) {\n requireAuthenticatedCallerExemptPaths =\n REQUIRE_AUTHENTICATED_CALLER_EXEMPT_PATHS.split(\",\")\n .map((path) => path.trim())\n .filter((path) => path.length > 0);\n }\n\n /**\n * Whether an attachment read is decided by the referencing document's own\n * policy rather than by the host's permission tables.\n *\n * Off by default, and a deployment's choice rather than something derived\n * from the flags around it. Which model governs those bytes is configuration\n * in the same sense the storage backend behind them is: a host that has said\n * nothing keeps exactly the behaviour it has, and one that wants the change\n * asks for it and can take it back without disturbing anything else.\n */\n let attachmentReadsFollowDocumentPolicy =\n configuredAttachmentPolicyReads ?? false;\n if (ATTACHMENT_READS_FOLLOW_DOCUMENT_POLICY !== undefined) {\n attachmentReadsFollowDocumentPolicy =\n ATTACHMENT_READS_FOLLOW_DOCUMENT_POLICY === \"true\";\n }\n\n if (ADMINS !== undefined) {\n admins = ADMINS.split(\",\").map((a) => a.toLowerCase());\n }\n\n let defaultProtection = false;\n if (DEFAULT_PROTECTION !== undefined) {\n defaultProtection = DEFAULT_PROTECTION.toLowerCase() === \"true\";\n }\n\n let skipCredentialVerification = false;\n if (SKIP_CREDENTIAL_VERIFICATION !== undefined) {\n skipCredentialVerification = SKIP_CREDENTIAL_VERIFICATION === \"true\";\n }\n\n let credentialVerificationCacheTtlMs: number | undefined;\n if (CREDENTIAL_VERIFICATION_CACHE_TTL_MS !== undefined) {\n const parsed = Number(CREDENTIAL_VERIFICATION_CACHE_TTL_MS);\n if (\n CREDENTIAL_VERIFICATION_CACHE_TTL_MS.trim() !== \"\" &&\n Number.isFinite(parsed) &&\n parsed >= 0\n ) {\n credentialVerificationCacheTtlMs = parsed;\n } else {\n logger.warn(\n `Ignoring invalid CREDENTIAL_VERIFICATION_CACHE_TTL_MS=\"${CREDENTIAL_VERIFICATION_CACHE_TTL_MS}\" (expected a non-negative number of milliseconds; 0 disables caching) — using the default TTL`,\n );\n }\n }\n\n const documentPermissionsRequested =\n options.documentPermissionService !== undefined ||\n DOCUMENT_PERMISSIONS_ENABLED === \"true\";\n assertAuthRequiredForDocumentPermissions(\n authEnabled,\n documentPermissionsRequested,\n );\n assertSkipCredentialVerificationAllowed(\n resolveCallerIdentity,\n skipCredentialVerification,\n process.env,\n );\n assertRequireAuthenticatedCallerAllowed(\n requireAuthenticatedCaller,\n resolveCallerIdentity,\n requireAuthenticatedCallerExemptPaths,\n );\n if (authEnabled && skipCredentialVerification) {\n logger.warn(\n \"SECURITY: SKIP_CREDENTIAL_VERIFICATION is enabled — Renown credential \" +\n \"verification is disabled and a bearer token's claimed address is NOT \" +\n \"cryptographically bound to its signing key. Identity is unverifiable; \" +\n \"use only in development or test.\",\n );\n }\n\n // Health check endpoint (registered directly on adapter, before auth)\n httpAdapter.getRoute(\"/health\", () => new Response(\"OK\", { status: 200 }));\n\n const readiness = createReadinessGate();\n httpAdapter.getRoute(\"/ready\", () =>\n readiness.isReady()\n ? new Response(\"OK\", { status: 200 })\n : new Response(\"starting\", { status: 503 }),\n );\n\n // Explorer route\n const explorerPrefix = getExplorerPrefix(config.basePath);\n httpAdapter.getRoute(`${explorerPrefix}/:endpoint?`, (request) => {\n const url = new URL(request.url);\n // Strip the prefix to find the optional :endpoint segment\n const suffix = url.pathname.slice(explorerPrefix.length).replace(/^\\//, \"\");\n const endpoint = suffix ? `/${suffix}` : \"/graphql\";\n // Prefer the document-scoped `explorerURLState` payload (produced by the\n // Connect DocumentToolbar) over the plain `?query=` parameter.\n const explorerState = decodeExplorerUrlState(\n url.searchParams.get(\"explorerURLState\") ?? \"\",\n );\n const query =\n explorerState?.query ?? url.searchParams.get(\"query\") ?? undefined;\n return new Response(\n renderGraphqlPlayground(\n endpoint,\n query,\n explorerState?.headers ?? {},\n explorerState?.variables,\n ),\n {\n headers: { \"Content-Type\": \"text/html\" },\n },\n );\n });\n\n /* Built whenever the bearer is read — which is not the same as the policy\n enforcing anything. `resolveCallerIdentity` defaults to `authEnabled`, so\n this is the same condition it always was unless a deployment opts in. */\n let authFetchMiddleware: AuthFetchMiddleware | undefined;\n let requireAuthFetchMiddleware: RequireAuthFetchMiddleware | undefined;\n let authService: AuthService | undefined;\n if (resolveCallerIdentity || authEnabled) {\n logger.info(\n \"Setting up Auth middleware (policy enforcement: @enabled, caller identity: @resolve)\",\n authEnabled,\n resolveCallerIdentity,\n );\n const renown =\n options.renown ??\n resolveRenownConfig(configuredRenown, process.env, logger);\n assertCredentialVerifierForSource(\n renown.source,\n options.verifyCredential !== undefined,\n );\n if (options.verifyCredential) {\n logger.info(\"Renown credentials will be verified by the host's verifier\");\n } else {\n logger.info(\n \"Renown credentials will be verified against @url\",\n renown.switchboardUrl ?? renown.url ?? \"the default Renown instance\",\n );\n }\n authService = new AuthService({\n enabled: authEnabled,\n resolveIdentity: resolveCallerIdentity,\n admins,\n skipCredentialVerification,\n credentialVerificationCacheTtlMs,\n verifyCredential:\n options.verifyCredential ??\n (await createRenownCredentialVerifier({\n renownUrl: renown.url,\n switchboardUrl: renown.switchboardUrl,\n })),\n });\n authFetchMiddleware = createAuthFetchMiddleware(authService);\n if (requireAuthenticatedCaller) {\n requireAuthFetchMiddleware = createRequireAuthFetchMiddleware(\n requireAuthenticatedCallerExemptPaths,\n );\n // The exempt paths are named in the log, not merely counted: the one\n // question an operator asks about this floor is what is still open, and\n // the answer should be in the boot output rather than in a manifest they\n // have to go and find.\n logger.info(\n requireAuthenticatedCallerExemptPaths.length > 0\n ? `Require-authenticated-caller middleware enabled: anonymous callers are rejected with a 401 before any subgraph, except on ${requireAuthenticatedCallerExemptPaths.join(\", \")}`\n : \"Require-authenticated-caller middleware enabled: anonymous callers are rejected with a 401 before any subgraph\",\n );\n } else {\n // Auth is on in some form, so say plainly what it is not doing. The\n // policy gates the reactor's own document reads; it does not gate a\n // package-provided subgraph, which authorizes nothing on its own. This\n // has always been true over HTTP, and WebSocket admission now matches it\n // rather than refusing tokenless connections on AUTH_ENABLED alone --\n // so a subscription reaches the same surface a query already did.\n logger.warn(\n \"Anonymous callers are admitted on every transport, including WebSocket \" +\n \"subscriptions: REQUIRE_AUTHENTICATED_CALLER is not set. The \" +\n \"authorization policy gates the reactor's own documents, but a \" +\n \"package-provided subgraph authorizes nothing on its own. Set \" +\n \"REQUIRE_AUTHENTICATED_CALLER=true to refuse anonymous callers before \" +\n \"any subgraph sees them.\",\n );\n }\n }\n\n const dbClosers: Array<() => Promise<void>> = [];\n\n // Initialize database and analytics store\n const {\n relationalDb,\n analyticsStore,\n closers: analyticsClosers,\n } = await initializeDatabaseAndAnalytics(\n options.dbPath,\n options.pgliteFactory,\n );\n dbClosers.push(...analyticsClosers);\n\n // Use provided document permission service, or create one if env var is set\n let documentPermissionService = options.documentPermissionService;\n if (!documentPermissionService && DOCUMENT_PERMISSIONS_ENABLED === \"true\") {\n const { db, knex, pglite } = getDbClient(\n options.dbPath,\n options.pgliteFactory,\n );\n dbClosers.push(...makeDbClosers(knex, pglite));\n // Run document permission migrations\n await runMigrations(db as Kysely<unknown>);\n logger.info(\"Document permission migrations completed\");\n documentPermissionService = new DocumentPermissionService(\n db as Kysely<DocumentPermissionDatabase>,\n { defaultProtection },\n );\n logger.info(\"Document permission service initialized\");\n }\n\n // The authorization policy collapses the prior dual enforcement paths into\n // one. Document permissions imply authentication (guaranteed by the boot\n // gate above). The service itself is created in _setupAPI, where the\n // reactor client needed for the parent-document resolver exists.\n const policy = documentPermissionService\n ? AuthorizationPolicy.DOCUMENT_PERMISSIONS\n : authEnabled\n ? AuthorizationPolicy.ADMIN_ONLY\n : AuthorizationPolicy.OPEN;\n const authorizationConfig: AuthorizationConfig = {\n admins,\n defaultProtection,\n policy,\n };\n\n // Initialize attachment service\n const attachmentStoragePath = resolveAttachmentStoragePath(options);\n await mkdir(attachmentStoragePath, { recursive: true });\n const {\n db: attachmentDb,\n knex: attachmentKnex,\n pglite: attachmentPglite,\n } = getDbClient(options.dbPath, options.pgliteFactory);\n dbClosers.push(...makeDbClosers(attachmentKnex, attachmentPglite));\n const ATTACHMENT_SWEEP_INTERVAL_MS = 60 * 60 * 1000; // hourly\n const attachmentBackend = await createStartupAttachmentBackend({\n db: attachmentDb as Kysely<AttachmentDatabase>,\n });\n const attachmentBuilder = new AttachmentBuilder(\n attachmentDb,\n attachmentStoragePath,\n ).withReservationSweepMs(ATTACHMENT_SWEEP_INTERVAL_MS);\n if (attachmentBackend) attachmentBuilder.withBackend(attachmentBackend);\n const attachments: AttachmentBuildResult = await attachmentBuilder.build();\n const attachmentReferenceIndex = await new AttachmentReferenceIndexBuilder(\n attachmentDb,\n ).build();\n dbClosers.push(() => {\n attachments.destroy();\n return Promise.resolve();\n });\n logger.info(\"Attachment service initialized\");\n\n // Initialize package manager\n const loaders: IPackageLoader[] = options.packageLoaders ?? [\n new ImportPackageLoader(),\n ];\n\n const packages = new PackageManager(loaders, {\n configFile: options.configFile,\n packages: options.packages ?? [],\n });\n\n // Package routes hang off <basePath>/api, webhooks off <basePath>/webhooks.\n // Created here rather than in the GraphQL manager because processors are\n // initialised before it exists.\n //\n // Webhook tokens live in the reactor's own database rather than per host, so\n // a URL a provider has registered keeps working across a restart and any\n // replica can serve it.\n const publicUrl = resolvePublicOrigin(port);\n const webhooks = new WebhookService({\n store: new RelationalWebhookStore(relationalDb),\n basePath: config.basePath,\n publicUrl,\n });\n const httpRoutes = new HttpRouteService({\n httpAdapter,\n basePath: config.basePath,\n authService,\n webhooks,\n publicUrl,\n // The reactor sits behind switchboard-lb in every deployed topology, so the\n // forwarded headers naming the public origin come from the balancer, not a caller.\n trustProxy: true,\n });\n // The endpoint family serves from a host scope rather than the adapter, so\n // one dispatch path covers package routes and webhooks alike.\n webhooks.attach(\n httpRoutes.hostScope(\n CORE_PACKAGE_NAME,\n path.posix.join(\"/\", config.basePath ?? \"/\", WEBHOOK_SEGMENT),\n ),\n );\n\n return {\n port,\n httpAdapter,\n httpRoutes,\n authFetchMiddleware,\n requireAuthFetchMiddleware,\n authService,\n relationalDb,\n analyticsStore,\n documentPermissionService,\n authorizationConfig,\n attachments,\n attachmentReferenceIndex,\n packages,\n dbClosers,\n readiness,\n attachmentReadsFollowDocumentPolicy,\n };\n}\n\n/**\n * Private helper function containing common setup logic for API initialization\n */\nasync function _setupAPI(\n reactorClient: IReactorClient,\n syncManager: ISyncManager,\n reactorProcessorManager: IReactorProcessorManager,\n httpAdapter: IHttpAdapter,\n authFetchMiddleware: AuthFetchMiddleware | undefined,\n requireAuthFetchMiddleware: RequireAuthFetchMiddleware | undefined,\n authService: AuthService | undefined,\n port: number,\n packages: PackageManager,\n relationalDb: IRelationalDb,\n analyticsStore: IAnalyticsStore,\n documentPermissionService: DocumentPermissionService | undefined,\n processors: Map<string, Processor>,\n subgraphs: Map<string, SubgraphClass[]>,\n options: Options,\n processorApp: ProcessorApp,\n readModels: IReadModel[],\n attachments: AttachmentBuildResult,\n attachmentReferenceIndex: AttachmentReferenceIndexBuildResult,\n attachmentReferenceProjection: AttachmentReferenceProjectionCapability,\n authorizationConfig: AuthorizationConfig,\n documentModelRegistry?: IDocumentModelRegistry,\n dbClosers: Array<() => Promise<void>> = [],\n reactorDriveClient?: IDriveClient,\n syncServingGate?: SyncScopeGate,\n httpRoutes?: HttpRouteService,\n attachmentReadsFollowDocumentPolicy = false,\n): Promise<API> {\n const hostModuleBase: IProcessorHostModule = {\n ...createReactorHostModuleBase({\n client: reactorClient,\n readModels,\n relationalDb,\n analyticsStore,\n processorApp,\n config: options.processorConfig,\n }),\n attachments: createAttachmentClient(attachments.service),\n };\n\n // Per package, so a processor's HTTP scope is bound to its own namespace and\n // cannot be swapped for another package's. Everything else is shared.\n const moduleFor = (packageName: string): IProcessorHostModule => ({\n ...hostModuleBase,\n http: httpRoutes?.scopeForOrNull(packageName),\n });\n const mcpServerEnabled = options.mcp ?? true;\n\n const logger = options.logger ?? defaultLogger;\n\n // initialize processors\n const configuredProcessorEntries = Object.entries(\n options.processors ?? {},\n ) as [string, ProcessorInitializer[]][];\n\n const processorEntries = [\n ...processors.entries(),\n ...configuredProcessorEntries,\n ] as [string, ProcessorInitializer[]][];\n\n for (const [packageName, fns] of processorEntries) {\n const factories = await Promise.allSettled(\n fns.map(async (fn) => {\n try {\n return fn(moduleFor(packageName));\n } catch (e) {\n logger.error(\n `Error initializing processor factory for package ${packageName}:`,\n e,\n );\n\n return null;\n }\n }),\n );\n\n const validFactories = factories.filter(\n (factory): factory is PromiseFulfilledResult<ProcessorFactory> =>\n factory.status === \"fulfilled\" &&\n factory.value !== null &&\n typeof factory.value === \"function\",\n );\n\n if (!validFactories.length) {\n continue;\n }\n\n // Register with the reactor ProcessorManager\n // Cast the results to ReactorProcessorRecord since the loaded factories\n // implement the reactor interface\n await reactorProcessorManager.registerFactory(\n packageName,\n async (driveHeader) =>\n (\n await Promise.all(\n validFactories.map(async ({ value: driveFactory }) => {\n try {\n const result = await driveFactory(driveHeader);\n return result as unknown as ReactorProcessorRecord[];\n } catch (e) {\n logger.error(\n `Error creating processor for drive ${driveHeader.id}:`,\n e,\n );\n\n return [];\n }\n }),\n )\n ).flat(),\n );\n }\n\n // Start the server\n const { httpServer, wsServer } = await startServer(\n httpAdapter,\n port,\n options.https,\n logger,\n );\n\n // Authorization service is always present; created here because the\n // parent-document resolver used for permission inheritance needs the\n // reactor client.\n const authorizationService = createAuthorizationService(\n authorizationConfig,\n documentPermissionService,\n createGetParentIdsFn(reactorClient),\n );\n logger.info(\n `Authorization service initialized (policy: ${authorizationConfig.policy})`,\n );\n\n // Attachment reads are authorized by the document read, the reactor's read\n // gate, and the projected document/ref relationship; the facade owns that\n // composition so routes never consult any of them directly.\n //\n // The document-read gate is the one sync serving already decides with, rather\n // than a second one built here: two gates over one document model would be\n // two policies that can disagree, and the question both are asking is the\n // same one — may this subject read this document's state.\n //\n // Handed over only when the host asks for it. Which model decides an\n // attachment read is a deployment's choice, the same way the storage backend\n // behind those bytes is, and a host that has not asked keeps the behaviour it\n // has — whatever else it has turned on.\n assertAttachmentPolicyReadsAllowed(\n attachmentReadsFollowDocumentPolicy,\n syncServingGate !== undefined,\n );\n const attachmentAccess: IAttachmentAccessService =\n new AttachmentAccessService(\n createCanonicalDocumentIdResolver(reactorClient),\n authorizationService,\n attachmentReferenceIndex.store,\n attachmentReferenceProjection,\n reactorClient,\n attachmentReadsFollowDocumentPolicy ? syncServingGate : undefined,\n );\n\n // set up subgraph manager\n const coreSubgraphs: SubgraphClass[] = DefaultCoreSubgraphs.slice();\n coreSubgraphs.push(ReactorSubgraph);\n\n // Register Auth subgraph when document permission service is available\n if (documentPermissionService) {\n coreSubgraphs.push(AuthSubgraph);\n logger.info(\"Auth subgraph registered (document permissions enabled)\");\n }\n\n const graphqlManager = await setupGraphQLManager(\n httpAdapter,\n authFetchMiddleware,\n requireAuthFetchMiddleware,\n httpServer,\n wsServer,\n reactorClient,\n relationalDb,\n analyticsStore,\n syncManager,\n {\n extended: subgraphs,\n core: coreSubgraphs,\n },\n logger.child([\"graphql-manager\"]),\n authorizationService,\n authService,\n documentPermissionService,\n options.enableDocumentModelSubgraphs,\n port,\n reactorDriveClient,\n syncServingGate,\n httpRoutes,\n );\n\n // Set up event listeners\n setupEventListeners(\n packages,\n graphqlManager,\n reactorProcessorManager,\n moduleFor,\n documentModelRegistry,\n );\n\n if (mcpServerEnabled) {\n await setupMcpServer(\n {\n client: reactorClient,\n syncManager,\n authorizeRequest: createMcpRequestAuthorizer(\n authService,\n authorizationService,\n ),\n },\n httpAdapter,\n );\n logger.info(`MCP server available at http://localhost:${port}/mcp`);\n }\n\n const dispose = buildApiDispose({\n graphqlManager,\n httpRoutes,\n httpServer,\n wsServer,\n dbClosers,\n logger,\n });\n\n return {\n httpAdapter,\n httpRoutes: httpRoutes ?? new HttpRouteService({ httpAdapter }),\n graphqlManager,\n packages,\n attachments,\n attachmentReferenceIndex,\n attachmentAccess,\n authService,\n // Read from the composed middleware rather than from a second pass over\n // the environment, and the same way `#makeWsContextFactory` reads it: the\n // middleware exists exactly when the floor is on, so one value cannot\n // disagree with another about whether this deployment serves anonymous\n // callers.\n requireAuthenticatedCaller: requireAuthFetchMiddleware !== undefined,\n // Handed back rather than kept private: a component the host composes\n // after boot (the workflow runtime) authorizes with this service and\n // stores in this database.\n authorizationService,\n relationalDb,\n dispose,\n };\n}\n\n/**\n * Composes the lifecycle teardown for an API instance. Steps run in\n * dependency order so that draining HTTP/GraphQL surfaces happens before the\n * underlying knex pool and PGlite WAL are released. Each step is wrapped in\n * its own try/catch — one failure must not strand the rest of the chain,\n * since this runs on the way to process exit.\n */\nfunction buildApiDispose(args: {\n graphqlManager: GraphQLManager;\n httpRoutes?: HttpRouteService;\n httpServer: http.Server;\n wsServer: WebSocketServer;\n dbClosers: Array<() => Promise<void>>;\n logger: ILogger;\n}): () => Promise<void> {\n const {\n graphqlManager,\n httpRoutes,\n httpServer,\n wsServer,\n dbClosers,\n logger,\n } = args;\n let disposed = false;\n return async () => {\n if (disposed) return;\n disposed = true;\n\n // Before the server closes: every package scope, and the host scopes with\n // them. Nothing downstream depends on the routes still being mounted, and\n // a handler answering during teardown is a handler holding a disposed\n // dependency.\n try {\n httpRoutes?.disposeAll();\n } catch (error) {\n logger.error(\"API dispose: releasing HTTP routes failed: @error\", error);\n }\n\n try {\n await graphqlManager.shutdown();\n } catch (error) {\n logger.error(\n \"API dispose: graphqlManager.shutdown failed: @error\",\n error,\n );\n }\n\n try {\n for (const client of wsServer.clients) client.terminate();\n await new Promise<void>((resolve) => wsServer.close(() => resolve()));\n } catch (error) {\n logger.error(\"API dispose: wsServer.close failed: @error\", error);\n }\n\n if (httpServer.listening) {\n try {\n // closeAllConnections forces idle keep-alives shut so close() can resolve;\n // otherwise SIGINT-driven shutdown stalls until the OS reaps the sockets.\n httpServer.closeAllConnections();\n await new Promise<void>((resolve, reject) =>\n httpServer.close((err) => (err ? reject(err) : resolve())),\n );\n } catch (error) {\n logger.error(\"API dispose: httpServer.close failed: @error\", error);\n }\n }\n\n for (const close of dbClosers) {\n try {\n await close();\n } catch (error) {\n logger.error(\"API dispose: db closer failed: @error\", error);\n }\n }\n };\n}\n\n/**\n * Initializes and starts the API server using an initializer function.\n * This function first loads packages to get document models, then calls the initializer function\n * to create the reactor client module with the appropriate dependencies.\n *\n * @param clientInitializer - Initializer function that creates the reactor client module with document models.\n * @param options - Additional options for server configuration.\n *\n * @returns The API server components along with the created client instances.\n */\n/**\n * Result of a client initializer. `reactorDriveClient` is optionally returned\n * alongside the reactor module so resolvers can dispatch reactor-drive parent\n * ops to it; legacy switchboards omit it.\n */\nexport interface ClientInitializerResult {\n module: InProcessReactorClientModule;\n reactorDriveClient?: IDriveClient;\n attachmentReferenceProjection?: AttachmentReferenceProjectionCapability;\n}\n\nexport interface ClientInitializerDependencies {\n attachmentReferenceWriter: IAttachmentReferenceWriter;\n /** Upgrade manifests exported by the loaded packages, one per type. */\n upgradeManifests: UpgradeManifest<readonly number[]>[];\n}\n\nexport type { AttachmentReferenceProjectionCapability } from \"./services/attachment-access.service.js\";\n\nexport async function initializeAndStartAPI(\n clientInitializer: (\n documentModels: DocumentModelModule[],\n dependencies: ClientInitializerDependencies,\n ) => Promise<ClientInitializerResult>,\n options: Options,\n processorApp: ProcessorApp,\n): Promise<\n API & {\n client: IReactorClient;\n syncManager: ISyncManager;\n documentModelRegistry: IDocumentModelRegistry;\n readiness: ReadinessGate;\n attachmentReferenceProjection: AttachmentReferenceProjectionCapability;\n packageManager: PackageManager;\n }\n> {\n const {\n port,\n httpAdapter,\n httpRoutes,\n authFetchMiddleware,\n requireAuthFetchMiddleware,\n authService,\n relationalDb,\n analyticsStore,\n documentPermissionService,\n authorizationConfig,\n attachments,\n attachmentReferenceIndex,\n packages,\n dbClosers,\n readiness,\n attachmentReadsFollowDocumentPolicy,\n } = await _setupCommonInfrastructure(options);\n\n const { documentModels, upgradeManifests, processors, subgraphs } =\n await packages.init();\n\n const {\n module: reactorClientModule,\n reactorDriveClient,\n attachmentReferenceProjection = {\n status: \"unavailable\",\n reason: \"initializer-did-not-report\",\n },\n } = await clientInitializer(documentModels, {\n attachmentReferenceWriter: attachmentReferenceIndex.store,\n upgradeManifests,\n });\n\n // Extract client and syncManager from the module\n const reactorClient = reactorClientModule.client;\n\n const syncManager =\n reactorClientModule.reactorModule?.syncModule?.syncManager;\n if (!syncManager) {\n throw new Error(\n \"SyncManager not available from InProcessReactorClientModule\",\n );\n }\n\n const reactorProcessorManager =\n reactorClientModule.reactorModule?.processorManager;\n if (!reactorProcessorManager) {\n throw new Error(\n \"ProcessorManager not available from InProcessReactorClientModule\",\n );\n }\n\n const documentModelRegistry =\n reactorClientModule.reactorModule?.documentModelRegistry;\n if (!documentModelRegistry) {\n throw new Error(\n \"DocumentModelRegistry not available from InProcessReactorClientModule\",\n );\n }\n\n const readModelCoordinator =\n reactorClientModule.reactorModule?.readModelCoordinator;\n const readModels = readModelCoordinator?.readModels ?? [];\n\n const api = await _setupAPI(\n reactorClient,\n syncManager,\n reactorProcessorManager,\n httpAdapter,\n authFetchMiddleware,\n requireAuthFetchMiddleware,\n authService,\n port,\n packages,\n relationalDb,\n analyticsStore,\n documentPermissionService,\n processors,\n subgraphs,\n options,\n processorApp,\n readModels,\n attachments,\n attachmentReferenceIndex,\n attachmentReferenceProjection,\n authorizationConfig,\n documentModelRegistry,\n dbClosers,\n reactorDriveClient,\n buildSyncServingGate(\n reactorClientModule.reactorModule,\n authorizationConfig,\n options.logger ?? defaultLogger,\n ),\n httpRoutes,\n attachmentReadsFollowDocumentPolicy,\n );\n\n return {\n ...api,\n client: reactorClient,\n syncManager,\n documentModelRegistry,\n readiness,\n attachmentReferenceProjection,\n packageManager: packages,\n };\n}\n\n/**\n * The origin to advertise in a webhook URL.\n *\n * A provider is a third party: it has to be given something it can resolve, so\n * a relative path is not an option. The platform variables come first, then a\n * bare deploy domain, and finally the local origin — which is right for `ph\n * dev` behind a tunnel and, at worst, obviously wrong rather than silently\n * unusable.\n */\nfunction resolvePublicOrigin(port: number): string {\n const explicit = process.env.PUBLIC_URL ?? process.env.RENDER_EXTERNAL_URL;\n if (explicit) return withScheme(explicit);\n const domain = process.env.HEROKU_APP_DEFAULT_DOMAIN_NAME;\n if (domain) return withScheme(domain);\n return `http://localhost:${port}`;\n}\n\nfunction withScheme(origin: string): string {\n const trimmed = origin.replace(/\\/+$/, \"\");\n return /^https?:\\/\\//.test(trimmed) ? trimmed : `https://${trimmed}`;\n}\n","export interface InstalledPackageInfo {\n name: string;\n version?: string;\n registryUrl: string;\n installedAt: Date;\n documentTypes: string[];\n}\n\nexport interface IPackageStorage {\n get(name: string): Promise<InstalledPackageInfo | undefined>;\n getAll(): Promise<InstalledPackageInfo[]>;\n set(name: string, info: InstalledPackageInfo): Promise<void>;\n delete(name: string): Promise<boolean>;\n has(name: string): Promise<boolean>;\n}\n\nexport class InMemoryPackageStorage implements IPackageStorage {\n private packages = new Map<string, InstalledPackageInfo>();\n\n get(name: string): Promise<InstalledPackageInfo | undefined> {\n return Promise.resolve(this.packages.get(name));\n }\n\n getAll(): Promise<InstalledPackageInfo[]> {\n return Promise.resolve(Array.from(this.packages.values()));\n }\n\n set(name: string, info: InstalledPackageInfo): Promise<void> {\n this.packages.set(name, info);\n return Promise.resolve();\n }\n\n delete(name: string): Promise<boolean> {\n return Promise.resolve(this.packages.delete(name));\n }\n\n has(name: string): Promise<boolean> {\n return Promise.resolve(this.packages.has(name));\n }\n}\n","import type { IDocumentModelRegistry } from \"@powerhousedao/reactor\";\nimport type { DocumentModelModule } from \"@powerhousedao/shared/document-model\";\nimport { childLogger } from \"document-model\";\nimport type { HttpPackageLoader } from \"../packages/http-loader.js\";\nimport type { IPackageManager } from \"../packages/types.js\";\nimport {\n InMemoryPackageStorage,\n type IPackageStorage,\n type InstalledPackageInfo,\n} from \"./package-storage.js\";\n\nexport interface InstallPackageResult {\n package: InstalledPackageInfo;\n documentModelsLoaded: number;\n}\n\nexport interface PackageManagementServiceOptions {\n storage?: IPackageStorage;\n defaultRegistryUrl?: string;\n httpLoader?: HttpPackageLoader;\n documentModelRegistry?: IDocumentModelRegistry;\n packageManager?: IPackageManager;\n}\n\nexport class PackageManagementService {\n private readonly storage: IPackageStorage;\n private readonly defaultRegistryUrl?: string;\n private readonly httpLoader?: HttpPackageLoader;\n private readonly documentModelRegistry?: IDocumentModelRegistry;\n private readonly packageManager?: IPackageManager;\n private readonly logger = childLogger([\n \"reactor-api\",\n \"package-management-service\",\n ]);\n\n private onModelsChanged?: (models: DocumentModelModule[]) => void;\n private loadedModulesCache = new Map<string, DocumentModelModule[]>();\n\n constructor(options: PackageManagementServiceOptions = {}) {\n this.storage = options.storage ?? new InMemoryPackageStorage();\n this.defaultRegistryUrl = options.defaultRegistryUrl;\n this.httpLoader = options.httpLoader;\n this.documentModelRegistry = options.documentModelRegistry;\n this.packageManager = options.packageManager;\n }\n\n setOnModelsChanged(callback: (models: DocumentModelModule[]) => void): void {\n this.onModelsChanged = callback;\n }\n\n async installPackage(\n name: string,\n registryUrl?: string,\n ): Promise<InstallPackageResult> {\n const url = registryUrl ?? this.defaultRegistryUrl;\n if (!url) {\n throw new Error(\n \"No registry URL provided and no default registry URL configured\",\n );\n }\n\n if (!this.httpLoader) {\n throw new Error(\"HttpPackageLoader not configured\");\n }\n\n const existing = await this.storage.get(name);\n if (existing) {\n throw new Error(`Package ${name} is already installed`);\n }\n\n this.logger.info(\"Installing package @name from @url\", name, url);\n\n const models = await this.httpLoader.loadDocumentModels(name);\n const documentTypes = models.map((m) => m.documentModel.global.id);\n\n const packageInfo: InstalledPackageInfo = {\n name,\n registryUrl: url,\n installedAt: new Date(),\n documentTypes,\n };\n\n await this.storage.set(name, packageInfo);\n this.loadedModulesCache.set(name, models);\n\n if (this.documentModelRegistry) {\n const results = this.documentModelRegistry.registerModules(...models);\n for (const result of results) {\n if (result.status === \"error\") {\n this.logger.error(\n \"Failed to register document model: @error\",\n result.error.message,\n );\n }\n }\n }\n\n this.logger.info(\n \"Installed package @name with @count document models\",\n name,\n models.length,\n );\n\n this.triggerModelsChanged();\n\n return {\n package: packageInfo,\n documentModelsLoaded: models.length,\n };\n }\n\n async uninstallPackage(name: string): Promise<boolean> {\n const existing = await this.storage.get(name);\n if (!existing) {\n this.logger.warn(\"Package @name is not installed\", name);\n return false;\n }\n\n this.logger.info(\"Uninstalling package @name\", name);\n\n await this.storage.delete(name);\n this.loadedModulesCache.delete(name);\n\n if (this.httpLoader) {\n this.httpLoader.documentModelLoader.removeFromCache(name);\n }\n\n if (this.documentModelRegistry) {\n this.documentModelRegistry.unregisterModules(...existing.documentTypes);\n }\n\n if (this.packageManager) {\n // Drop the package from the manager's maps so the subgraph and\n // processor teardown listeners run for everything it registered.\n this.packageManager.removePackage(name);\n }\n\n this.triggerModelsChanged();\n\n this.logger.info(\"Uninstalled package @name\", name);\n return true;\n }\n\n async getInstalledPackages(): Promise<InstalledPackageInfo[]> {\n return this.storage.getAll();\n }\n\n async getInstalledPackage(\n name: string,\n ): Promise<InstalledPackageInfo | undefined> {\n return this.storage.get(name);\n }\n\n getAllLoadedModules(): DocumentModelModule[] {\n const allModules: DocumentModelModule[] = [];\n for (const modules of this.loadedModulesCache.values()) {\n allModules.push(...modules);\n }\n return allModules;\n }\n\n private triggerModelsChanged(): void {\n if (this.onModelsChanged) {\n const allModules = this.getAllLoadedModules();\n this.onModelsChanged(allModules);\n }\n }\n}\n"],"names":["schemaSource","resolvers.documentAccess","resolvers.userDocumentPermissions","resolvers.operationPermissions","resolvers.canExecuteOperation","resolvers.documentProtection","resolvers.setDocumentProtection","resolvers.transferDocumentOwnership","resolvers.grantDocumentPermission","resolvers.revokeDocumentPermission","resolvers.grantOperationPermission","resolvers.revokeOperationPermission","logger","DEFAULT_MAX_BODY_BYTES","logger","scalarsTypeDefs","typeDefs","z","PropagationMode","documentResolver","findDocumentsResolver","documentOutgoingRelationshipsResolver","documentIncomingRelationshipsResolver","createDocumentWithInitialStateResolver","createEmptyDocumentResolver","schemaSource","resolvers.installedPackages","resolvers.installedPackage","resolvers.installPackage","resolvers.uninstallPackage","actionObj","schemaSource","resolvers.documentOperations","resolvers.documentModels","resolvers.document","resolvers.documentOutgoingRelationships","resolvers.documentIncomingRelationships","resolvers.documentOutgoingRelationshipEdges","resolvers.documentIncomingRelationshipEdges","resolvers.findDocuments","resolvers.jobStatus","resolvers.evaluateActions","resolvers.collectHeldSyncOperations","resolvers.pollSyncEnvelopes","resolvers.createDocument","resolvers.createEmptyDocument","resolvers.execute","resolvers.executeAsync","resolvers.mutateDocument","resolvers.mutateDocumentAsync","resolvers.renameDocument","resolvers.setPreferredEditor","resolvers.addRelationship","resolvers.updateRelationship","resolvers.removeRelationship","resolvers.moveRelationship","resolvers.deleteDocument","resolvers.deleteDocuments","resolvers.touchChannel","resolvers.pushSyncEnvelopes","loadDocumentModelsUtil","loadSubgraphsUtil","loadProcessorsUtil","up","down","up","down","migration001","migration002","migration003"],"mappings":"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;GACzC,OAAO,UAIL,mCACA,WACA,OACF;EACF;EACA,iCACE,WACA,SACgD;GAChD,OAAO,UAIL,0CACA,WACA,OACF;EACF;EACA,iCACE,WACA,SACgD;GAChD,OAAO,UAIL,0CACA,WACA,OACF;EACF;EACA,qCACE,WACA,SACoD;GACpD,OAAO,UAIL,8CACA,WACA,OACF;EACF;EACA,qCACE,WACA,SACoD;GACpD,OAAO,UAIL,8CACA,WACA,OACF;EACF;EACA,cACE,WACA,SAC6B;GAC7B,OAAO,UACL,uBACA,WACA,OACF;EACF;EACA,sBACE,WACA,SACqC;GACrC,OAAO,UAIL,+BACA,WACA,OACF;EACF;EACA,aACE,WACA,SAC4B;GAC5B,OAAO,UACL,sBACA,WACA,OACF;EACF;EACA,gBACE,WACA,SAC+B;GAC/B,OAAO,UACL,yBACA,WACA,OACF;EACF;EACA,eACE,WACA,SACiC;GACjC,OAAO,UACL,wBACA,WACA,OACF;EACF;EACA,oBACE,WACA,SACsC;GACtC,OAAO,UAIL,6BACA,WACA,OACF;EACF;EACA,eACE,WACA,SACiC;GACjC,OAAO,UACL,wBACA,WACA,OACF;EACF;EACA,oBACE,WACA,SACsC;GACtC,OAAO,UAIL,6BACA,WACA,OACF;EACF;EACA,eACE,WACA,SACiC;GACjC,OAAO,UACL,wBACA,WACA,OACF;EACF;EACA,mBACE,WACA,SACqC;GACrC,OAAO,UAIL,4BACA,WACA,OACF;EACF;EACA,gBACE,WACA,SACkC;GAClC,OAAO,UAIL,yBACA,WACA,OACF;EACF;EACA,mBACE,WACA,SACqC;GACrC,OAAO,UAIL,4BACA,WACA,OACF;EACF;EACA,mBACE,WACA,SACqC;GACrC,OAAO,UAIL,4BACA,WACA,OACF;EACF;EACA,iBACE,WACA,SACmC;GACnC,OAAO,UAIL,0BACA,WACA,OACF;EACF;EACA,eACE,WACA,SACiC;GACjC,OAAO,UACL,wBACA,WACA,OACF;EACF;EACA,gBACE,WACA,SACkC;GAClC,OAAO,UAIL,yBACA,WAC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","debug_id":"5c9c63cc-7da0-5a74-ae18-1418ddd6118f"}