@rytass/bpm-core-nestjs-module 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/LICENSE +21 -0
- package/README.md +837 -0
- package/package.json +168 -0
- package/src/index.d.ts +14 -0
- package/src/index.js +18 -0
- package/src/index.js.map +1 -0
- package/src/lib/attachment/attachment-options.d.ts +44 -0
- package/src/lib/attachment/attachment-options.js +62 -0
- package/src/lib/attachment/attachment-options.js.map +1 -0
- package/src/lib/attachment/attachment-storage.provider.d.ts +4 -0
- package/src/lib/attachment/attachment-storage.provider.js +35 -0
- package/src/lib/attachment/attachment-storage.provider.js.map +1 -0
- package/src/lib/attachment/attachment-storage.token.d.ts +3 -0
- package/src/lib/attachment/attachment-storage.token.js +5 -0
- package/src/lib/attachment/attachment-storage.token.js.map +1 -0
- package/src/lib/attachment/attachment.controller.d.ts +8 -0
- package/src/lib/attachment/attachment.controller.js +38 -0
- package/src/lib/attachment/attachment.controller.js.map +1 -0
- package/src/lib/attachment/attachment.entity.d.ts +14 -0
- package/src/lib/attachment/attachment.entity.js +74 -0
- package/src/lib/attachment/attachment.entity.js.map +1 -0
- package/src/lib/attachment/attachment.module.d.ts +27 -0
- package/src/lib/attachment/attachment.module.js +103 -0
- package/src/lib/attachment/attachment.module.js.map +1 -0
- package/src/lib/attachment/attachment.mutations.d.ts +8 -0
- package/src/lib/attachment/attachment.mutations.js +35 -0
- package/src/lib/attachment/attachment.mutations.js.map +1 -0
- package/src/lib/attachment/attachment.queries.d.ts +9 -0
- package/src/lib/attachment/attachment.queries.js +78 -0
- package/src/lib/attachment/attachment.queries.js.map +1 -0
- package/src/lib/attachment/attachment.service.d.ts +49 -0
- package/src/lib/attachment/attachment.service.js +276 -0
- package/src/lib/attachment/attachment.service.js.map +1 -0
- package/src/lib/attachment/dto/upload-attachment.input.d.ts +11 -0
- package/src/lib/attachment/dto/upload-attachment.input.js +68 -0
- package/src/lib/attachment/dto/upload-attachment.input.js.map +1 -0
- package/src/lib/attachment/index.d.ts +5 -0
- package/src/lib/attachment/index.js +9 -0
- package/src/lib/attachment/index.js.map +1 -0
- package/src/lib/bpm/bpm-root.module.d.ts +155 -0
- package/src/lib/bpm/bpm-root.module.js +170 -0
- package/src/lib/bpm/bpm-root.module.js.map +1 -0
- package/src/lib/bpm/index.d.ts +1 -0
- package/src/lib/bpm/index.js +5 -0
- package/src/lib/bpm/index.js.map +1 -0
- package/src/lib/bpm-auth/bpm-auth-context.d.ts +24 -0
- package/src/lib/bpm-auth/bpm-auth-context.extractor.d.ts +4 -0
- package/src/lib/bpm-auth/bpm-auth-context.extractor.js +69 -0
- package/src/lib/bpm-auth/bpm-auth-context.extractor.js.map +1 -0
- package/src/lib/bpm-auth/bpm-auth-context.js +15 -0
- package/src/lib/bpm-auth/bpm-auth-context.js.map +1 -0
- package/src/lib/bpm-auth/bpm-auth.authorization.d.ts +12 -0
- package/src/lib/bpm-auth/bpm-auth.authorization.js +67 -0
- package/src/lib/bpm-auth/bpm-auth.authorization.js.map +1 -0
- package/src/lib/bpm-auth/bpm-auth.decorators.d.ts +3 -0
- package/src/lib/bpm-auth/bpm-auth.decorators.js +11 -0
- package/src/lib/bpm-auth/bpm-auth.decorators.js.map +1 -0
- package/src/lib/bpm-auth/bpm-auth.guard.d.ts +7 -0
- package/src/lib/bpm-auth/bpm-auth.guard.js +24 -0
- package/src/lib/bpm-auth/bpm-auth.guard.js.map +1 -0
- package/src/lib/bpm-auth/bpm-auth.module.d.ts +6 -0
- package/src/lib/bpm-auth/bpm-auth.module.js +69 -0
- package/src/lib/bpm-auth/bpm-auth.module.js.map +1 -0
- package/src/lib/bpm-auth/bpm-auth.options.d.ts +11 -0
- package/src/lib/bpm-auth/bpm-auth.options.js +3 -0
- package/src/lib/bpm-auth/bpm-auth.options.js.map +1 -0
- package/src/lib/bpm-auth/configurable-bpm-auth-context.accessor.d.ts +10 -0
- package/src/lib/bpm-auth/configurable-bpm-auth-context.accessor.js +40 -0
- package/src/lib/bpm-auth/configurable-bpm-auth-context.accessor.js.map +1 -0
- package/src/lib/bpm-auth/index.d.ts +6 -0
- package/src/lib/bpm-auth/index.js +10 -0
- package/src/lib/bpm-auth/index.js.map +1 -0
- package/src/lib/common/filters/all-exceptions.filter.d.ts +25 -0
- package/src/lib/common/filters/all-exceptions.filter.js +93 -0
- package/src/lib/common/filters/all-exceptions.filter.js.map +1 -0
- package/src/lib/common/index.d.ts +1 -0
- package/src/lib/common/index.js +5 -0
- package/src/lib/common/index.js.map +1 -0
- package/src/lib/common/iso-duration.d.ts +1 -0
- package/src/lib/common/iso-duration.js +27 -0
- package/src/lib/common/iso-duration.js.map +1 -0
- package/src/lib/condition/condition.module.d.ts +2 -0
- package/src/lib/condition/condition.module.js +16 -0
- package/src/lib/condition/condition.module.js.map +1 -0
- package/src/lib/condition/condition.service.d.ts +16 -0
- package/src/lib/condition/condition.service.js +82 -0
- package/src/lib/condition/condition.service.js.map +1 -0
- package/src/lib/condition/index.d.ts +2 -0
- package/src/lib/condition/index.js +6 -0
- package/src/lib/condition/index.js.map +1 -0
- package/src/lib/database/data-source.d.ts +4 -0
- package/src/lib/database/data-source.js +7 -0
- package/src/lib/database/data-source.js.map +1 -0
- package/src/lib/database/index.d.ts +2 -0
- package/src/lib/database/index.js +6 -0
- package/src/lib/database/index.js.map +1 -0
- package/src/lib/database/migration-runner.d.ts +1 -0
- package/src/lib/database/migration-runner.js +23 -0
- package/src/lib/database/migration-runner.js.map +1 -0
- package/src/lib/database/typeorm.config.d.ts +14 -0
- package/src/lib/database/typeorm.config.js +135 -0
- package/src/lib/database/typeorm.config.js.map +1 -0
- package/src/lib/delegation/delegation-rule.entity.d.ts +19 -0
- package/src/lib/delegation/delegation-rule.entity.js +99 -0
- package/src/lib/delegation/delegation-rule.entity.js.map +1 -0
- package/src/lib/delegation/delegation.enums.d.ts +10 -0
- package/src/lib/delegation/delegation.enums.js +23 -0
- package/src/lib/delegation/delegation.enums.js.map +1 -0
- package/src/lib/delegation/delegation.module.d.ts +2 -0
- package/src/lib/delegation/delegation.module.js +22 -0
- package/src/lib/delegation/delegation.module.js.map +1 -0
- package/src/lib/delegation/delegation.mutations.d.ts +11 -0
- package/src/lib/delegation/delegation.mutations.js +87 -0
- package/src/lib/delegation/delegation.mutations.js.map +1 -0
- package/src/lib/delegation/delegation.queries.d.ts +10 -0
- package/src/lib/delegation/delegation.queries.js +91 -0
- package/src/lib/delegation/delegation.queries.js.map +1 -0
- package/src/lib/delegation/delegation.service.d.ts +56 -0
- package/src/lib/delegation/delegation.service.js +268 -0
- package/src/lib/delegation/delegation.service.js.map +1 -0
- package/src/lib/delegation/dto/delegation-rule.input.d.ts +24 -0
- package/src/lib/delegation/dto/delegation-rule.input.js +143 -0
- package/src/lib/delegation/dto/delegation-rule.input.js.map +1 -0
- package/src/lib/delegation/index.d.ts +5 -0
- package/src/lib/delegation/index.js +9 -0
- package/src/lib/delegation/index.js.map +1 -0
- package/src/lib/form/dto/form-definition.input.d.ts +21 -0
- package/src/lib/form/dto/form-definition.input.js +103 -0
- package/src/lib/form/dto/form-definition.input.js.map +1 -0
- package/src/lib/form/form-definition-version.entity.d.ts +17 -0
- package/src/lib/form/form-definition-version.entity.js +84 -0
- package/src/lib/form/form-definition-version.entity.js.map +1 -0
- package/src/lib/form/form-definition.entity.d.ts +13 -0
- package/src/lib/form/form-definition.entity.js +66 -0
- package/src/lib/form/form-definition.entity.js.map +1 -0
- package/src/lib/form/form-schema-lint.object.d.ts +4 -0
- package/src/lib/form/form-schema-lint.object.js +20 -0
- package/src/lib/form/form-schema-lint.object.js.map +1 -0
- package/src/lib/form/form-schema.validator.d.ts +13 -0
- package/src/lib/form/form-schema.validator.js +354 -0
- package/src/lib/form/form-schema.validator.js.map +1 -0
- package/src/lib/form/form.enums.d.ts +9 -0
- package/src/lib/form/form.enums.js +22 -0
- package/src/lib/form/form.enums.js.map +1 -0
- package/src/lib/form/form.module.d.ts +2 -0
- package/src/lib/form/form.module.js +27 -0
- package/src/lib/form/form.module.js.map +1 -0
- package/src/lib/form/form.mutations.d.ts +14 -0
- package/src/lib/form/form.mutations.js +88 -0
- package/src/lib/form/form.mutations.js.map +1 -0
- package/src/lib/form/form.queries.d.ts +16 -0
- package/src/lib/form/form.queries.js +96 -0
- package/src/lib/form/form.queries.js.map +1 -0
- package/src/lib/form/form.service.d.ts +35 -0
- package/src/lib/form/form.service.js +297 -0
- package/src/lib/form/form.service.js.map +1 -0
- package/src/lib/form/index.d.ts +8 -0
- package/src/lib/form/index.js +12 -0
- package/src/lib/form/index.js.map +1 -0
- package/src/lib/identity/identity-options.d.ts +13 -0
- package/src/lib/identity/identity-options.js +20 -0
- package/src/lib/identity/identity-options.js.map +1 -0
- package/src/lib/identity/identity.module.d.ts +17 -0
- package/src/lib/identity/identity.module.js +65 -0
- package/src/lib/identity/identity.module.js.map +1 -0
- package/src/lib/identity/identity.queries.d.ts +12 -0
- package/src/lib/identity/identity.queries.js +79 -0
- package/src/lib/identity/identity.queries.js.map +1 -0
- package/src/lib/identity/identity.service.d.ts +22 -0
- package/src/lib/identity/identity.service.js +141 -0
- package/src/lib/identity/identity.service.js.map +1 -0
- package/src/lib/identity/index.d.ts +3 -0
- package/src/lib/identity/index.js +7 -0
- package/src/lib/identity/index.js.map +1 -0
- package/src/lib/identity/member-base.adapter.d.ts +95 -0
- package/src/lib/identity/member-base.adapter.js +137 -0
- package/src/lib/identity/member-base.adapter.js.map +1 -0
- package/src/lib/identity/member-metadata-cache.entity.d.ts +8 -0
- package/src/lib/identity/member-metadata-cache.entity.js +39 -0
- package/src/lib/identity/member-metadata-cache.entity.js.map +1 -0
- package/src/lib/identity/member-profile.object.d.ts +8 -0
- package/src/lib/identity/member-profile.object.js +37 -0
- package/src/lib/identity/member-profile.object.js.map +1 -0
- package/src/lib/identity/member-resolver.interface.d.ts +41 -0
- package/src/lib/identity/member-resolver.interface.js +19 -0
- package/src/lib/identity/member-resolver.interface.js.map +1 -0
- package/src/lib/migrations/0000000000000-enable-postgres-extensions.d.ts +6 -0
- package/src/lib/migrations/0000000000000-enable-postgres-extensions.js +17 -0
- package/src/lib/migrations/0000000000000-enable-postgres-extensions.js.map +1 -0
- package/src/lib/migrations/0000000001000-identity-organization-foundation.d.ts +6 -0
- package/src/lib/migrations/0000000001000-identity-organization-foundation.js +97 -0
- package/src/lib/migrations/0000000001000-identity-organization-foundation.js.map +1 -0
- package/src/lib/migrations/0000000002000-form-builder-foundation.d.ts +6 -0
- package/src/lib/migrations/0000000002000-form-builder-foundation.js +66 -0
- package/src/lib/migrations/0000000002000-form-builder-foundation.js.map +1 -0
- package/src/lib/migrations/0000000003000-approval-template-foundation.d.ts +6 -0
- package/src/lib/migrations/0000000003000-approval-template-foundation.js +70 -0
- package/src/lib/migrations/0000000003000-approval-template-foundation.js.map +1 -0
- package/src/lib/migrations/0000000004000-workflow-engine-foundation.d.ts +6 -0
- package/src/lib/migrations/0000000004000-workflow-engine-foundation.js +134 -0
- package/src/lib/migrations/0000000004000-workflow-engine-foundation.js.map +1 -0
- package/src/lib/migrations/0000000005000-delegation-rules.d.ts +6 -0
- package/src/lib/migrations/0000000005000-delegation-rules.js +46 -0
- package/src/lib/migrations/0000000005000-delegation-rules.js.map +1 -0
- package/src/lib/migrations/0000000006000-notifications-sla.d.ts +6 -0
- package/src/lib/migrations/0000000006000-notifications-sla.js +70 -0
- package/src/lib/migrations/0000000006000-notifications-sla.js.map +1 -0
- package/src/lib/migrations/0000000007000-signatures-attachments.d.ts +6 -0
- package/src/lib/migrations/0000000007000-signatures-attachments.js +93 -0
- package/src/lib/migrations/0000000007000-signatures-attachments.js.map +1 -0
- package/src/lib/migrations/0000000008000-approval-template-categories.d.ts +6 -0
- package/src/lib/migrations/0000000008000-approval-template-categories.js +92 -0
- package/src/lib/migrations/0000000008000-approval-template-categories.js.map +1 -0
- package/src/lib/migrations/0000000009000-task-candidates.d.ts +6 -0
- package/src/lib/migrations/0000000009000-task-candidates.js +97 -0
- package/src/lib/migrations/0000000009000-task-candidates.js.map +1 -0
- package/src/lib/migrations/0000000010000-notification-delivery-state.d.ts +6 -0
- package/src/lib/migrations/0000000010000-notification-delivery-state.js +38 -0
- package/src/lib/migrations/0000000010000-notification-delivery-state.js.map +1 -0
- package/src/lib/migrations/0000000011000-remove-attachment-encryption-key.d.ts +6 -0
- package/src/lib/migrations/0000000011000-remove-attachment-encryption-key.js +22 -0
- package/src/lib/migrations/0000000011000-remove-attachment-encryption-key.js.map +1 -0
- package/src/lib/migrations/0000000012000-notification-sla-idempotency.d.ts +6 -0
- package/src/lib/migrations/0000000012000-notification-sla-idempotency.js +21 -0
- package/src/lib/migrations/0000000012000-notification-sla-idempotency.js.map +1 -0
- package/src/lib/migrations/0000000013000-workflow-query-indexes.d.ts +6 -0
- package/src/lib/migrations/0000000013000-workflow-query-indexes.js +80 -0
- package/src/lib/migrations/0000000013000-workflow-query-indexes.js.map +1 -0
- package/src/lib/migrations/index.d.ts +16 -0
- package/src/lib/migrations/index.js +49 -0
- package/src/lib/migrations/index.js.map +1 -0
- package/src/lib/notification/dto/notification-preference.input.d.ts +9 -0
- package/src/lib/notification/dto/notification-preference.input.js +53 -0
- package/src/lib/notification/dto/notification-preference.input.js.map +1 -0
- package/src/lib/notification/index.d.ts +7 -0
- package/src/lib/notification/index.js +11 -0
- package/src/lib/notification/index.js.map +1 -0
- package/src/lib/notification/notification-delivery-scheduler.service.d.ts +13 -0
- package/src/lib/notification/notification-delivery-scheduler.service.js +53 -0
- package/src/lib/notification/notification-delivery-scheduler.service.js.map +1 -0
- package/src/lib/notification/notification-delivery.service.d.ts +23 -0
- package/src/lib/notification/notification-delivery.service.js +245 -0
- package/src/lib/notification/notification-delivery.service.js.map +1 -0
- package/src/lib/notification/notification-dispatcher.token.d.ts +7 -0
- package/src/lib/notification/notification-dispatcher.token.js +5 -0
- package/src/lib/notification/notification-dispatcher.token.js.map +1 -0
- package/src/lib/notification/notification-options.d.ts +215 -0
- package/src/lib/notification/notification-options.js +128 -0
- package/src/lib/notification/notification-options.js.map +1 -0
- package/src/lib/notification/notification-options.module.d.ts +23 -0
- package/src/lib/notification/notification-options.module.js +41 -0
- package/src/lib/notification/notification-options.module.js.map +1 -0
- package/src/lib/notification/notification-preference.entity.d.ts +10 -0
- package/src/lib/notification/notification-preference.entity.js +50 -0
- package/src/lib/notification/notification-preference.entity.js.map +1 -0
- package/src/lib/notification/notification-sla-scheduler.service.d.ts +13 -0
- package/src/lib/notification/notification-sla-scheduler.service.js +51 -0
- package/src/lib/notification/notification-sla-scheduler.service.js.map +1 -0
- package/src/lib/notification/notification-template.d.ts +13 -0
- package/src/lib/notification/notification-template.js +61 -0
- package/src/lib/notification/notification-template.js.map +1 -0
- package/src/lib/notification/notification.entity.d.ts +23 -0
- package/src/lib/notification/notification.entity.js +122 -0
- package/src/lib/notification/notification.entity.js.map +1 -0
- package/src/lib/notification/notification.enums.d.ts +24 -0
- package/src/lib/notification/notification.enums.js +45 -0
- package/src/lib/notification/notification.enums.js.map +1 -0
- package/src/lib/notification/notification.module.d.ts +2 -0
- package/src/lib/notification/notification.module.js +45 -0
- package/src/lib/notification/notification.module.js.map +1 -0
- package/src/lib/notification/notification.mutations.d.ts +11 -0
- package/src/lib/notification/notification.mutations.js +64 -0
- package/src/lib/notification/notification.mutations.js.map +1 -0
- package/src/lib/notification/notification.queries.d.ts +11 -0
- package/src/lib/notification/notification.queries.js +77 -0
- package/src/lib/notification/notification.queries.js.map +1 -0
- package/src/lib/notification/notification.service.d.ts +81 -0
- package/src/lib/notification/notification.service.js +621 -0
- package/src/lib/notification/notification.service.js.map +1 -0
- package/src/lib/organization/dto/manager-resolution.input.d.ts +18 -0
- package/src/lib/organization/dto/manager-resolution.input.js +107 -0
- package/src/lib/organization/dto/manager-resolution.input.js.map +1 -0
- package/src/lib/organization/dto/membership.input.d.ts +16 -0
- package/src/lib/organization/dto/membership.input.js +99 -0
- package/src/lib/organization/dto/membership.input.js.map +1 -0
- package/src/lib/organization/dto/org-unit.input.d.ts +24 -0
- package/src/lib/organization/dto/org-unit.input.js +119 -0
- package/src/lib/organization/dto/org-unit.input.js.map +1 -0
- package/src/lib/organization/dto/position.input.d.ts +13 -0
- package/src/lib/organization/dto/position.input.js +70 -0
- package/src/lib/organization/dto/position.input.js.map +1 -0
- package/src/lib/organization/index.d.ts +12 -0
- package/src/lib/organization/index.js +16 -0
- package/src/lib/organization/index.js.map +1 -0
- package/src/lib/organization/json-metadata.d.ts +1 -0
- package/src/lib/organization/json-metadata.js +14 -0
- package/src/lib/organization/json-metadata.js.map +1 -0
- package/src/lib/organization/manager-resolution.entity.d.ts +11 -0
- package/src/lib/organization/manager-resolution.entity.js +55 -0
- package/src/lib/organization/manager-resolution.entity.js.map +1 -0
- package/src/lib/organization/membership.entity.d.ts +11 -0
- package/src/lib/organization/membership.entity.js +60 -0
- package/src/lib/organization/membership.entity.js.map +1 -0
- package/src/lib/organization/org-unit-tree-commit-result.object.d.ts +4 -0
- package/src/lib/organization/org-unit-tree-commit-result.object.js +17 -0
- package/src/lib/organization/org-unit-tree-commit-result.object.js.map +1 -0
- package/src/lib/organization/org-unit.entity.d.ts +13 -0
- package/src/lib/organization/org-unit.entity.js +64 -0
- package/src/lib/organization/org-unit.entity.js.map +1 -0
- package/src/lib/organization/organization-summary.object.d.ts +6 -0
- package/src/lib/organization/organization-summary.object.js +28 -0
- package/src/lib/organization/organization-summary.object.js.map +1 -0
- package/src/lib/organization/organization.enums.d.ts +11 -0
- package/src/lib/organization/organization.enums.js +22 -0
- package/src/lib/organization/organization.enums.js.map +1 -0
- package/src/lib/organization/organization.module.d.ts +2 -0
- package/src/lib/organization/organization.module.js +35 -0
- package/src/lib/organization/organization.module.js.map +1 -0
- package/src/lib/organization/organization.mutations.d.ts +26 -0
- package/src/lib/organization/organization.mutations.js +148 -0
- package/src/lib/organization/organization.mutations.js.map +1 -0
- package/src/lib/organization/organization.queries.d.ts +23 -0
- package/src/lib/organization/organization.queries.js +202 -0
- package/src/lib/organization/organization.queries.js.map +1 -0
- package/src/lib/organization/organization.service.d.ts +102 -0
- package/src/lib/organization/organization.service.js +751 -0
- package/src/lib/organization/organization.service.js.map +1 -0
- package/src/lib/organization/position.entity.d.ts +9 -0
- package/src/lib/organization/position.entity.js +48 -0
- package/src/lib/organization/position.entity.js.map +1 -0
- package/src/lib/organization/resolved-manager.object.d.ts +4 -0
- package/src/lib/organization/resolved-manager.object.js +20 -0
- package/src/lib/organization/resolved-manager.object.js.map +1 -0
- package/src/lib/signature/index.d.ts +4 -0
- package/src/lib/signature/index.js +8 -0
- package/src/lib/signature/index.js.map +1 -0
- package/src/lib/signature/signature-options.d.ts +33 -0
- package/src/lib/signature/signature-options.js +51 -0
- package/src/lib/signature/signature-options.js.map +1 -0
- package/src/lib/signature/signature-verification.object.d.ts +6 -0
- package/src/lib/signature/signature-verification.object.js +28 -0
- package/src/lib/signature/signature-verification.object.js.map +1 -0
- package/src/lib/signature/signature.entity.d.ts +16 -0
- package/src/lib/signature/signature.entity.js +88 -0
- package/src/lib/signature/signature.entity.js.map +1 -0
- package/src/lib/signature/signature.module.d.ts +11 -0
- package/src/lib/signature/signature.module.js +60 -0
- package/src/lib/signature/signature.module.js.map +1 -0
- package/src/lib/signature/signature.queries.d.ts +11 -0
- package/src/lib/signature/signature.queries.js +46 -0
- package/src/lib/signature/signature.queries.js.map +1 -0
- package/src/lib/signature/signature.service.d.ts +25 -0
- package/src/lib/signature/signature.service.js +124 -0
- package/src/lib/signature/signature.service.js.map +1 -0
- package/src/lib/template/approval-template-category.entity.d.ts +9 -0
- package/src/lib/template/approval-template-category.entity.js +49 -0
- package/src/lib/template/approval-template-category.entity.js.map +1 -0
- package/src/lib/template/approval-template-version.entity.d.ts +21 -0
- package/src/lib/template/approval-template-version.entity.js +106 -0
- package/src/lib/template/approval-template-version.entity.js.map +1 -0
- package/src/lib/template/approval-template.entity.d.ts +14 -0
- package/src/lib/template/approval-template.entity.js +74 -0
- package/src/lib/template/approval-template.entity.js.map +1 -0
- package/src/lib/template/dto/approval-template.input.d.ts +36 -0
- package/src/lib/template/dto/approval-template.input.js +187 -0
- package/src/lib/template/dto/approval-template.input.js.map +1 -0
- package/src/lib/template/index.d.ts +8 -0
- package/src/lib/template/index.js +12 -0
- package/src/lib/template/index.js.map +1 -0
- package/src/lib/template/template.enums.d.ts +14 -0
- package/src/lib/template/template.enums.js +31 -0
- package/src/lib/template/template.enums.js.map +1 -0
- package/src/lib/template/template.module.d.ts +2 -0
- package/src/lib/template/template.module.js +33 -0
- package/src/lib/template/template.module.js.map +1 -0
- package/src/lib/template/template.mutations.d.ts +20 -0
- package/src/lib/template/template.mutations.js +139 -0
- package/src/lib/template/template.mutations.js.map +1 -0
- package/src/lib/template/template.queries.d.ts +16 -0
- package/src/lib/template/template.queries.js +133 -0
- package/src/lib/template/template.queries.js.map +1 -0
- package/src/lib/template/template.service.d.ts +64 -0
- package/src/lib/template/template.service.js +521 -0
- package/src/lib/template/template.service.js.map +1 -0
- package/src/lib/template/workflow-definition.validator.d.ts +9 -0
- package/src/lib/template/workflow-definition.validator.js +362 -0
- package/src/lib/template/workflow-definition.validator.js.map +1 -0
- package/src/lib/testing/cel-js.jest.d.ts +15 -0
- package/src/lib/testing/cel-js.jest.js +27 -0
- package/src/lib/testing/cel-js.jest.js.map +1 -0
- package/src/lib/workflow-engine/activity-log.entity.d.ts +12 -0
- package/src/lib/workflow-engine/activity-log.entity.js +62 -0
- package/src/lib/workflow-engine/activity-log.entity.js.map +1 -0
- package/src/lib/workflow-engine/approval-instance-page-info.object.d.ts +8 -0
- package/src/lib/workflow-engine/approval-instance-page-info.object.js +36 -0
- package/src/lib/workflow-engine/approval-instance-page-info.object.js.map +1 -0
- package/src/lib/workflow-engine/approval-instance.entity.d.ts +22 -0
- package/src/lib/workflow-engine/approval-instance.entity.js +113 -0
- package/src/lib/workflow-engine/approval-instance.entity.js.map +1 -0
- package/src/lib/workflow-engine/dto/cancel-approval-instance.input.d.ts +5 -0
- package/src/lib/workflow-engine/dto/cancel-approval-instance.input.js +29 -0
- package/src/lib/workflow-engine/dto/cancel-approval-instance.input.js.map +1 -0
- package/src/lib/workflow-engine/dto/decide-task.input.d.ts +9 -0
- package/src/lib/workflow-engine/dto/decide-task.input.js +47 -0
- package/src/lib/workflow-engine/dto/decide-task.input.js.map +1 -0
- package/src/lib/workflow-engine/dto/dry-run-approval-workflow.input.d.ts +6 -0
- package/src/lib/workflow-engine/dto/dry-run-approval-workflow.input.js +34 -0
- package/src/lib/workflow-engine/dto/dry-run-approval-workflow.input.js.map +1 -0
- package/src/lib/workflow-engine/dto/resubmit-approval-instance.input.d.ts +6 -0
- package/src/lib/workflow-engine/dto/resubmit-approval-instance.input.js +34 -0
- package/src/lib/workflow-engine/dto/resubmit-approval-instance.input.js.map +1 -0
- package/src/lib/workflow-engine/dto/submit-approval-instance.input.d.ts +7 -0
- package/src/lib/workflow-engine/dto/submit-approval-instance.input.js +40 -0
- package/src/lib/workflow-engine/dto/submit-approval-instance.input.js.map +1 -0
- package/src/lib/workflow-engine/index.d.ts +20 -0
- package/src/lib/workflow-engine/index.js +24 -0
- package/src/lib/workflow-engine/index.js.map +1 -0
- package/src/lib/workflow-engine/task-candidate.entity.d.ts +14 -0
- package/src/lib/workflow-engine/task-candidate.entity.js +72 -0
- package/src/lib/workflow-engine/task-candidate.entity.js.map +1 -0
- package/src/lib/workflow-engine/task-decision.entity.d.ts +12 -0
- package/src/lib/workflow-engine/task-decision.entity.js +60 -0
- package/src/lib/workflow-engine/task-decision.entity.js.map +1 -0
- package/src/lib/workflow-engine/task.entity.d.ts +20 -0
- package/src/lib/workflow-engine/task.entity.js +109 -0
- package/src/lib/workflow-engine/task.entity.js.map +1 -0
- package/src/lib/workflow-engine/workflow-condition-evaluator.d.ts +5 -0
- package/src/lib/workflow-engine/workflow-condition-evaluator.js +107 -0
- package/src/lib/workflow-engine/workflow-condition-evaluator.js.map +1 -0
- package/src/lib/workflow-engine/workflow-dashboard-summary.object.d.ts +8 -0
- package/src/lib/workflow-engine/workflow-dashboard-summary.object.js +36 -0
- package/src/lib/workflow-engine/workflow-dashboard-summary.object.js.map +1 -0
- package/src/lib/workflow-engine/workflow-dry-run.object.d.ts +21 -0
- package/src/lib/workflow-engine/workflow-dry-run.object.js +86 -0
- package/src/lib/workflow-engine/workflow-dry-run.object.js.map +1 -0
- package/src/lib/workflow-engine/workflow-engine.enums.d.ts +58 -0
- package/src/lib/workflow-engine/workflow-engine.enums.js +95 -0
- package/src/lib/workflow-engine/workflow-engine.enums.js.map +1 -0
- package/src/lib/workflow-engine/workflow-engine.module.d.ts +9 -0
- package/src/lib/workflow-engine/workflow-engine.module.js +76 -0
- package/src/lib/workflow-engine/workflow-engine.module.js.map +1 -0
- package/src/lib/workflow-engine/workflow-engine.mutations.d.ts +19 -0
- package/src/lib/workflow-engine/workflow-engine.mutations.js +106 -0
- package/src/lib/workflow-engine/workflow-engine.mutations.js.map +1 -0
- package/src/lib/workflow-engine/workflow-engine.queries.d.ts +29 -0
- package/src/lib/workflow-engine/workflow-engine.queries.js +225 -0
- package/src/lib/workflow-engine/workflow-engine.queries.js.map +1 -0
- package/src/lib/workflow-engine/workflow-engine.service.d.ts +145 -0
- package/src/lib/workflow-engine/workflow-engine.service.js +2785 -0
- package/src/lib/workflow-engine/workflow-engine.service.js.map +1 -0
- package/src/lib/workflow-engine/workflow-engine.tokens.d.ts +9 -0
- package/src/lib/workflow-engine/workflow-engine.tokens.js +5 -0
- package/src/lib/workflow-engine/workflow-engine.tokens.js.map +1 -0
- package/src/lib/workflow-engine/workflow-service-task-dispatcher.token.d.ts +18 -0
- package/src/lib/workflow-engine/workflow-service-task-dispatcher.token.js +39 -0
- package/src/lib/workflow-engine/workflow-service-task-dispatcher.token.js.map +1 -0
- package/src/lib/workflow-engine/workflow-token.entity.d.ts +10 -0
- package/src/lib/workflow-engine/workflow-token.entity.js +50 -0
- package/src/lib/workflow-engine/workflow-token.entity.js.map +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,837 @@
|
|
|
1
|
+
# @rytass/bpm-core-nestjs-module
|
|
2
|
+
|
|
3
|
+
Embeddable NestJS module for BPM approval workflows.
|
|
4
|
+
|
|
5
|
+
This package provides the backend BPM domain layer: GraphQL resolvers, TypeORM
|
|
6
|
+
entities, migrations, workflow execution, approval tasks, form definitions,
|
|
7
|
+
approval templates, organization/member lookup contracts, delegation,
|
|
8
|
+
notifications, SLA handling, attachments, and decision signatures.
|
|
9
|
+
|
|
10
|
+
It is designed to be embedded into a host NestJS application. The host
|
|
11
|
+
application owns runtime infrastructure such as GraphQL setup, TypeORM
|
|
12
|
+
connection setup, auth/session handling, Vault or secret loading, member
|
|
13
|
+
directory integration, storage adapters, and deployment.
|
|
14
|
+
|
|
15
|
+
## Package Status
|
|
16
|
+
|
|
17
|
+
Current version: `0.0.1`
|
|
18
|
+
|
|
19
|
+
The package is intended for NestJS backend hosts. It does not include the
|
|
20
|
+
Next.js backoffice UI and does not provide a production auth system by itself.
|
|
21
|
+
|
|
22
|
+
Frontend / cross-framework consumers should use
|
|
23
|
+
[`@rytass/bpm-core-client`](../bpm-core-client/README.md) for the GraphQL
|
|
24
|
+
transport, REST auth client, and pre-baked typed operations against this
|
|
25
|
+
backend module.
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pnpm add @rytass/bpm-core-nestjs-module @rytass/bpm-core-shared
|
|
31
|
+
pnpm add @nestjs/common @nestjs/core @nestjs/graphql @nestjs/typeorm graphql typeorm reflect-metadata
|
|
32
|
+
pnpm add pg
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**TypeScript moduleResolution**: prefer `node16`, `nodenext`, or `bundler` in
|
|
36
|
+
your `tsconfig.json` so the package's `exports` field is honored. Classic
|
|
37
|
+
`moduleResolution: "node"` also works through the `typesVersions` fallback
|
|
38
|
+
shipped with this package, but is on TypeScript's long-term deprecation
|
|
39
|
+
path — new hosts should opt in to modern resolution.
|
|
40
|
+
|
|
41
|
+
If your host uses Apollo GraphQL:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pnpm add @nestjs/apollo @apollo/server
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
If your host uses Vault-backed database settings:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pnpm add @rytass/secret-adapter-vault-nestjs
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Runtime Responsibilities
|
|
54
|
+
|
|
55
|
+
`@rytass/bpm-core-nestjs-module` owns BPM domain behavior.
|
|
56
|
+
|
|
57
|
+
Your host application must provide:
|
|
58
|
+
|
|
59
|
+
- A NestJS application runtime.
|
|
60
|
+
- A configured `GraphQLModule`.
|
|
61
|
+
- A configured TypeORM `DataSource` / `TypeOrmModule`.
|
|
62
|
+
- Auth/session/JWT logic.
|
|
63
|
+
- A `BPMAuthContext` bridge from the request execution context.
|
|
64
|
+
- A `BPM_MEMBER_RESOLVER` provider for member metadata lookup.
|
|
65
|
+
- Attachment storage configuration when local storage is not acceptable.
|
|
66
|
+
- A dedicated worker or host dispatcher when email/webhook/SLA work should not
|
|
67
|
+
run inside API replicas.
|
|
68
|
+
- Production secrets for attachment URL signing, signatures, SMTP, webhook, and Vault.
|
|
69
|
+
|
|
70
|
+
The package intentionally stores member IDs instead of owning user accounts.
|
|
71
|
+
Member profiles, roles, permissions, and email addresses are resolved by the
|
|
72
|
+
host.
|
|
73
|
+
|
|
74
|
+
## Quick Start
|
|
75
|
+
|
|
76
|
+
The host must wire the same authenticated member into both GraphQL context and
|
|
77
|
+
`BPMRootModule`. BPM expects host root-level routing — do **not** call Nest's
|
|
78
|
+
`setGlobalPrefix()`. BPM controllers (notably `AttachmentController`) hardcode
|
|
79
|
+
relative paths and use `attachmentRoutePrefix` to mount themselves; if you
|
|
80
|
+
want a prefix in production URLs, set `attachmentRoutePrefix` or push the
|
|
81
|
+
prefix into a reverse proxy.
|
|
82
|
+
|
|
83
|
+
A minimal host module looks like this:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
import { Module } from '@nestjs/common';
|
|
87
|
+
import { GraphQLModule } from '@nestjs/graphql';
|
|
88
|
+
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
89
|
+
import { ApolloDriver, type ApolloDriverConfig } from '@nestjs/apollo';
|
|
90
|
+
import { BPMRootModule, BPM_MEMBER_RESOLVER, buildTypeOrmModuleOptions } from '@rytass/bpm-core-nestjs-module';
|
|
91
|
+
import { VaultModule, VaultService } from '@rytass/secret-adapter-vault-nestjs';
|
|
92
|
+
import type { Request } from 'express';
|
|
93
|
+
import { buildBPMAuthContextFromExecutionContext } from './bpm-auth-context';
|
|
94
|
+
import { HostAuthModule } from './host-auth.module';
|
|
95
|
+
import { HostBPMMemberResolver } from './host-bpm-member.resolver';
|
|
96
|
+
import { HostSessionService } from './host-session.service';
|
|
97
|
+
|
|
98
|
+
@Module({
|
|
99
|
+
imports: [
|
|
100
|
+
HostAuthModule,
|
|
101
|
+
VaultModule.forRoot({
|
|
102
|
+
path: process.env.VAULT_PATH ?? 'bpm_core/develop',
|
|
103
|
+
}),
|
|
104
|
+
TypeOrmModule.forRootAsync({
|
|
105
|
+
imports: [VaultModule],
|
|
106
|
+
inject: [VaultService],
|
|
107
|
+
useFactory: buildTypeOrmModuleOptions,
|
|
108
|
+
}),
|
|
109
|
+
GraphQLModule.forRootAsync<ApolloDriverConfig>({
|
|
110
|
+
driver: ApolloDriver,
|
|
111
|
+
imports: [HostAuthModule],
|
|
112
|
+
inject: [HostSessionService],
|
|
113
|
+
useFactory: (sessionService: HostSessionService) => ({
|
|
114
|
+
autoSchemaFile: true,
|
|
115
|
+
context: async ({ req }: { readonly req?: Request }) => ({
|
|
116
|
+
bpmAuthContext: await sessionService.readBPMAuthContextFromRequest(req),
|
|
117
|
+
req,
|
|
118
|
+
}),
|
|
119
|
+
driver: ApolloDriver,
|
|
120
|
+
path: '/graphql',
|
|
121
|
+
sortSchema: true,
|
|
122
|
+
}),
|
|
123
|
+
}),
|
|
124
|
+
BPMRootModule.forRoot({
|
|
125
|
+
imports: [HostAuthModule],
|
|
126
|
+
authContextFactory: buildBPMAuthContextFromExecutionContext,
|
|
127
|
+
memberResolverProvider: {
|
|
128
|
+
provide: BPM_MEMBER_RESOLVER,
|
|
129
|
+
useExisting: HostBPMMemberResolver,
|
|
130
|
+
},
|
|
131
|
+
}),
|
|
132
|
+
],
|
|
133
|
+
})
|
|
134
|
+
export class AppModule {}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Auth Context
|
|
138
|
+
|
|
139
|
+
BPM guards and mutations need the current BPM member. The host may provide the
|
|
140
|
+
context in the GraphQL context object and expose it through
|
|
141
|
+
`authContextFactory`.
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
import type { ExecutionContext } from '@nestjs/common';
|
|
145
|
+
import { GqlExecutionContext } from '@nestjs/graphql';
|
|
146
|
+
import type { BPMAuthContext } from '@rytass/bpm-core-nestjs-module';
|
|
147
|
+
|
|
148
|
+
interface HostGraphQLContext {
|
|
149
|
+
readonly bpmAuthContext?: BPMAuthContext | null;
|
|
150
|
+
readonly req?: {
|
|
151
|
+
readonly bpmAuthContext?: BPMAuthContext | null;
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function buildBPMAuthContextFromExecutionContext(context?: ExecutionContext): BPMAuthContext | null {
|
|
156
|
+
if (!context) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const graphqlContext = GqlExecutionContext.create(context).getContext<HostGraphQLContext | undefined>();
|
|
161
|
+
|
|
162
|
+
return graphqlContext?.bpmAuthContext ?? graphqlContext?.req?.bpmAuthContext ?? null;
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`BPMAuthContext` shape:
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
export interface BPMAuthContext {
|
|
170
|
+
readonly memberId: string;
|
|
171
|
+
readonly metadata: Readonly<Record<string, unknown>>;
|
|
172
|
+
readonly permissions: readonly string[];
|
|
173
|
+
readonly roles: readonly string[];
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
BPM also exports param decorators so host resolvers don't need to call
|
|
178
|
+
`authContextFactory` directly:
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
import {
|
|
182
|
+
BPMAuthenticated,
|
|
183
|
+
BPMCurrentAuthContext,
|
|
184
|
+
BPMCurrentMemberId,
|
|
185
|
+
type BPMAuthContext,
|
|
186
|
+
} from '@rytass/bpm-core-nestjs-module';
|
|
187
|
+
|
|
188
|
+
@Resolver()
|
|
189
|
+
class HostResolver {
|
|
190
|
+
@Query(() => HostSummary)
|
|
191
|
+
@BPMAuthenticated()
|
|
192
|
+
hostSummary(
|
|
193
|
+
@BPMCurrentAuthContext() auth: BPMAuthContext,
|
|
194
|
+
@BPMCurrentMemberId() memberId: string,
|
|
195
|
+
): HostSummary {
|
|
196
|
+
return buildHostSummary(auth, memberId);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Role and Permission Contract
|
|
202
|
+
|
|
203
|
+
BPM guards inspect `BPMAuthContext.roles` and `BPMAuthContext.permissions` with
|
|
204
|
+
exact-string matching. The host must inject one of the following strings to
|
|
205
|
+
clear admin / designer guards; otherwise BPM resolvers reject with
|
|
206
|
+
`ForbiddenException`.
|
|
207
|
+
|
|
208
|
+
| Tier | Accepted roles or permissions | Guards / decorators / helpers |
|
|
209
|
+
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
|
210
|
+
| Admin | `roles: ['BPM_ADMIN']`; or `permissions` contains one of `bpm:*`, `bpm:admin`, `bpm.admin`, `bpm:admin:*` | `BPMAdminGuard`, `@BPMAdminOnly()`, `isBPMAdmin(authContext)` |
|
|
211
|
+
| Designer | Includes admin; or `roles: ['BPM_DESIGNER']`; or `permissions` contains one of `bpm:design`, `bpm.design`, `bpm.form.design`, `bpm.template.design`, `bpm:form:design`, `bpm:template:design` | `BPMDesignerGuard`, `@BPMDesignerOnly()`, `isBPMDesigner(authContext)` |
|
|
212
|
+
| Authenticated | `BPMAuthContext.memberId` is non-empty | `BPMAuthenticatedGuard`, `@BPMAuthenticated()` |
|
|
213
|
+
|
|
214
|
+
`@BPMAdminOnly()` and `@BPMDesignerOnly()` already chain
|
|
215
|
+
`BPMAuthenticatedGuard`. The host does not need to add `@BPMAuthenticated()`
|
|
216
|
+
on top of them.
|
|
217
|
+
|
|
218
|
+
## Member Resolver
|
|
219
|
+
|
|
220
|
+
The package resolves display names, email addresses, and approver candidates
|
|
221
|
+
through `BPM_MEMBER_RESOLVER`.
|
|
222
|
+
|
|
223
|
+
For a member-base-like directory, prefer the package helper. It creates a Nest
|
|
224
|
+
provider without forcing BPM to depend on the host identity package:
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
import { Injectable, type InjectionToken, type Provider } from '@nestjs/common';
|
|
228
|
+
import { BPM_MEMBER_RESOLVER, type BPMMemberBaseDirectory, createBPMMemberBaseResolverProvider } from '@rytass/bpm-core-nestjs-module';
|
|
229
|
+
|
|
230
|
+
interface HostMember {
|
|
231
|
+
readonly email: string;
|
|
232
|
+
readonly id: string;
|
|
233
|
+
readonly name: string;
|
|
234
|
+
readonly permissions: readonly string[];
|
|
235
|
+
readonly roles: readonly string[];
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
@Injectable()
|
|
239
|
+
export class HostMemberDirectory implements BPMMemberBaseDirectory<HostMember> {
|
|
240
|
+
async resolveMember(memberId: string): Promise<HostMember | null> {
|
|
241
|
+
return findHostMember(memberId);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async searchMembers(searchText: string): Promise<readonly HostMember[]> {
|
|
245
|
+
return searchHostMembers(searchText);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export const HOST_MEMBER_DIRECTORY: InjectionToken<BPMMemberBaseDirectory<HostMember>> = Symbol('HOST_MEMBER_DIRECTORY');
|
|
250
|
+
|
|
251
|
+
export const hostMemberProviders: readonly Provider[] = [
|
|
252
|
+
{
|
|
253
|
+
provide: HOST_MEMBER_DIRECTORY,
|
|
254
|
+
useClass: HostMemberDirectory,
|
|
255
|
+
},
|
|
256
|
+
createBPMMemberBaseResolverProvider({
|
|
257
|
+
adapterOptions: {
|
|
258
|
+
readEmail: (member): string => member.email,
|
|
259
|
+
readMemberId: (member): string => member.id,
|
|
260
|
+
readName: (member): string => member.name,
|
|
261
|
+
},
|
|
262
|
+
directoryToken: HOST_MEMBER_DIRECTORY,
|
|
263
|
+
provide: BPM_MEMBER_RESOLVER,
|
|
264
|
+
}),
|
|
265
|
+
];
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Required resolver contract:
|
|
269
|
+
|
|
270
|
+
```ts
|
|
271
|
+
export interface BPMMemberResolver {
|
|
272
|
+
resolve(memberId: string): Promise<MemberMetadata>;
|
|
273
|
+
resolveMany(memberIds: readonly string[]): Promise<ReadonlyMap<string, MemberMetadata>>;
|
|
274
|
+
search?(searchText: string): Promise<readonly MemberMetadata[]>;
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Root Module Configuration
|
|
279
|
+
|
|
280
|
+
Use `BPMRootModule.forRoot()` for static configuration or
|
|
281
|
+
`BPMRootModule.forRootAsync()` when values come from Vault, ConfigService, KMS,
|
|
282
|
+
or another secret provider.
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
BPMRootModule.forRootAsync({
|
|
286
|
+
imports: [ConfigModule],
|
|
287
|
+
inject: [ConfigService],
|
|
288
|
+
memberResolverProvider: {
|
|
289
|
+
provide: BPM_MEMBER_RESOLVER,
|
|
290
|
+
useClass: HostBPMMemberResolver,
|
|
291
|
+
},
|
|
292
|
+
useFactory: (config: ConfigService) => ({
|
|
293
|
+
authContextFactory: buildBPMAuthContextFromExecutionContext,
|
|
294
|
+
attachmentPublicBaseUrl: config.getOrThrow<string>('BPM_API_PUBLIC_URL'),
|
|
295
|
+
attachmentSignedUrlSecret: config.getOrThrow<string>('BPM_ATTACHMENT_SIGNING_SECRET'),
|
|
296
|
+
attachmentSignedUrlTtlSeconds: 300,
|
|
297
|
+
identityMemberMetadataCacheTtlMs: 300_000,
|
|
298
|
+
notificationEmailEnabled: 'auto',
|
|
299
|
+
notificationEmailFrom: config.get<string>('BPM_NOTIFICATION_FROM'),
|
|
300
|
+
notificationEmailSmtpHost: config.get<string>('BPM_SMTP_HOST'),
|
|
301
|
+
notificationEmailSmtpPassword: config.get<string>('BPM_SMTP_PASSWORD'),
|
|
302
|
+
notificationEmailSmtpPort: Number(config.get<string>('BPM_SMTP_PORT')),
|
|
303
|
+
notificationEmailSmtpSecure: false,
|
|
304
|
+
notificationEmailSmtpUsername: config.get<string>('BPM_SMTP_USERNAME'),
|
|
305
|
+
notificationWebhookEnabled: 'auto',
|
|
306
|
+
notificationWebhookEndpointUrl: config.get<string>('BPM_WEBHOOK_URL'),
|
|
307
|
+
notificationWebhookSigningSecret: config.get<string>('BPM_WEBHOOK_SIGNING_SECRET'),
|
|
308
|
+
signatureCurrentKeyVersion: 1,
|
|
309
|
+
signatureKeyProvider: {
|
|
310
|
+
readKey: (keyVersion: number): string => config.getOrThrow<string>(`BPM_SIGNATURE_KEY_V${keyVersion}`),
|
|
311
|
+
},
|
|
312
|
+
signatureTimestampProvider: {
|
|
313
|
+
createTimestampToken: ({ signedAt, signedPayloadHash }): Buffer => Buffer.from(JSON.stringify({ signedAt, signedPayloadHash }), 'utf8'),
|
|
314
|
+
},
|
|
315
|
+
}),
|
|
316
|
+
});
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Configuration Reference
|
|
320
|
+
|
|
321
|
+
| Option | Default | Description |
|
|
322
|
+
| ------------------------------------------------ | ------------------------------ | -------------------------------------------------------------- |
|
|
323
|
+
| `authContextFactory` | `undefined` | Reads `BPMAuthContext` from NestJS `ExecutionContext`. |
|
|
324
|
+
| `memberResolverProvider` | required | Provider for `BPM_MEMBER_RESOLVER`. |
|
|
325
|
+
| `attachmentStorageProvider` | local `.storage/attachments` | Host-provided `@rytass/storages` adapter. |
|
|
326
|
+
| `workflowServiceTaskDispatcherProvider` | built-in `fetch` dispatcher | Host provider for executable workflow `WEBHOOK` service tasks. |
|
|
327
|
+
| `attachmentRoutePrefix` | `/attachments` | Drives both the BPM signed URL path and the Nest controller mount path for `AttachmentController`. Must be set at module wiring time (see "Attachment Storage" below). |
|
|
328
|
+
| `attachmentStorageProviderId` | `local` | Value stored on attachment metadata for the active adapter. |
|
|
329
|
+
| `attachmentPublicBaseUrl` | `http://localhost:17603` | Public base URL for signed attachment URLs. |
|
|
330
|
+
| `attachmentSignedUrlSecret` | local development secret | HMAC secret for signed attachment download/preview tokens. |
|
|
331
|
+
| `attachmentSignedUrlTtlSeconds` | `300` | Signed attachment URL lifetime in seconds. |
|
|
332
|
+
| `identityMemberMetadataCacheTtlMs` | `300000` | Member metadata cache TTL. |
|
|
333
|
+
| `notificationInAppEnabled` | `true` | Enables in-app notification records. |
|
|
334
|
+
| `notificationEmailEnabled` | `auto` | Enables email when SMTP settings are complete. |
|
|
335
|
+
| `notificationEmailSmtpHost` | `null` | SMTP host. |
|
|
336
|
+
| `notificationEmailSmtpPort` | `null` | SMTP port. |
|
|
337
|
+
| `notificationEmailSmtpSecure` | `false` | `true` for implicit TLS, `false` for STARTTLS. |
|
|
338
|
+
| `notificationEmailSmtpUsername` | `null` | SMTP username. |
|
|
339
|
+
| `notificationEmailSmtpPassword` | `null` | SMTP password or app password. |
|
|
340
|
+
| `notificationEmailFrom` | `null` | Email sender address. |
|
|
341
|
+
| `notificationWebhookEnabled` | `auto` | Enables webhook when URL and signing secret are complete. |
|
|
342
|
+
| `notificationWebhookEndpointUrl` | `null` | Default webhook endpoint URL. |
|
|
343
|
+
| `notificationWebhookSigningSecret` | `null` | HMAC secret for webhook payload signatures. |
|
|
344
|
+
| `notificationDeliverySchedulerEnabled` | `false` | Runs pending email/webhook delivery loop in this process. |
|
|
345
|
+
| `notificationDeliveryScanIntervalMs` | `30000` | Delivery scheduler interval. |
|
|
346
|
+
| `notificationDeliveryBatchSize` | `25` | Maximum pending notifications per delivery scan. |
|
|
347
|
+
| `notificationDeliveryMaxAttempts` | `3` | Attempts before a notification is marked failed. |
|
|
348
|
+
| `notificationDeliveryRetryBaseDelayMs` | `60000` | Base retry delay multiplied by attempt count. |
|
|
349
|
+
| `notificationSlaSchedulerEnabled` | `false` | Runs automatic SLA scan loop in this process. |
|
|
350
|
+
| `notificationSlaScanIntervalMs` | `60000` | SLA scheduler interval. |
|
|
351
|
+
| `notificationSlaTimeoutRemindEnabled` | `true` | Enables SLA timeout `REMIND`. |
|
|
352
|
+
| `notificationSlaTimeoutAutoApproveEnabled` | `false` | Enables SLA timeout `AUTO_APPROVE`. |
|
|
353
|
+
| `notificationSlaTimeoutEscalateEnabled` | `false` | Enables SLA timeout `ESCALATE`. |
|
|
354
|
+
| `notificationSlaTimeoutTerminateInstanceEnabled` | `false` | Enables SLA timeout `TERMINATE_INSTANCE`. |
|
|
355
|
+
| `notificationTemplateEngine` | `simple` | `simple` only — `handlebars` is reserved and currently rendered as `simple`. |
|
|
356
|
+
| `notificationDefaultChannels` | `[IN_APP]` | Fallback channels when a workflow node has no channel list. |
|
|
357
|
+
| `notificationDefaultEmailDigestMode` | `INSTANT` | Default digest mode for missing preferences. |
|
|
358
|
+
| `notificationDefaultInAppPreferenceEnabled` | `true` | Default in-app preference for missing preferences. |
|
|
359
|
+
| `notificationDefaultEmailPreferenceEnabled` | `true` | Default email preference for missing preferences. |
|
|
360
|
+
| `signatureCurrentKeyVersion` | `1` | Key version used for new signatures. |
|
|
361
|
+
| `signatureKeyProvider` | local development key provider | Host key provider for signing and verification. |
|
|
362
|
+
| `signatureTimestampProvider` | mock timestamp provider | Host timestamp token provider. |
|
|
363
|
+
|
|
364
|
+
Production deployments should override all local development secrets.
|
|
365
|
+
|
|
366
|
+
## Database Setup
|
|
367
|
+
|
|
368
|
+
The package exports helpers for Vault-backed TypeORM setup:
|
|
369
|
+
|
|
370
|
+
```ts
|
|
371
|
+
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
372
|
+
import { VaultModule, VaultService } from '@rytass/secret-adapter-vault-nestjs';
|
|
373
|
+
import { buildTypeOrmModuleOptions } from '@rytass/bpm-core-nestjs-module';
|
|
374
|
+
|
|
375
|
+
TypeOrmModule.forRootAsync({
|
|
376
|
+
imports: [VaultModule],
|
|
377
|
+
inject: [VaultService],
|
|
378
|
+
useFactory: buildTypeOrmModuleOptions,
|
|
379
|
+
});
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
Expected Vault keys:
|
|
383
|
+
|
|
384
|
+
| Key | Description |
|
|
385
|
+
| ----------- | -------------------------- |
|
|
386
|
+
| `DB_HOST` | PostgreSQL host. |
|
|
387
|
+
| `DB_PORT` | PostgreSQL port, optional. |
|
|
388
|
+
| `DB_NAME` | PostgreSQL database name. |
|
|
389
|
+
| `DB_USER` | PostgreSQL username. |
|
|
390
|
+
| `DB_PASS` | PostgreSQL password. |
|
|
391
|
+
| `DB_SCHEMA` | PostgreSQL schema. |
|
|
392
|
+
|
|
393
|
+
`buildTypeOrmModuleOptions` adds `autoLoadEntities: true` so the NestJS
|
|
394
|
+
`TypeOrmModule` picks up BPM entities through each domain module's
|
|
395
|
+
`TypeOrmModule.forFeature`. `buildBPMDataSourceOptions()` returns
|
|
396
|
+
`entities: []` because TypeORM CLI tooling reads entities from the host's own
|
|
397
|
+
glob; if you plan to run `typeorm migration:generate` or
|
|
398
|
+
`typeorm migration:show` from a script, attach BPM entities to the data
|
|
399
|
+
source yourself.
|
|
400
|
+
|
|
401
|
+
Use `buildBPMDataSourceOptions()` when your host already has database secrets
|
|
402
|
+
and does not want the Vault adapter:
|
|
403
|
+
|
|
404
|
+
```ts
|
|
405
|
+
import { buildBPMDataSourceOptions } from '@rytass/bpm-core-nestjs-module';
|
|
406
|
+
|
|
407
|
+
const dataSourceOptions = buildBPMDataSourceOptions({
|
|
408
|
+
database: 'bpm_core',
|
|
409
|
+
host: '127.0.0.1',
|
|
410
|
+
password: 'secret',
|
|
411
|
+
port: 5432,
|
|
412
|
+
schema: 'bpm_core_staging',
|
|
413
|
+
username: 'bpm_core_staging',
|
|
414
|
+
});
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
The local migration CLI helper can also read Vault directly from environment
|
|
418
|
+
variables:
|
|
419
|
+
|
|
420
|
+
```bash
|
|
421
|
+
VAULT_HOST=https://vault.example.com \
|
|
422
|
+
VAULT_ACCOUNT=your-account \
|
|
423
|
+
VAULT_PASSWORD=your-password \
|
|
424
|
+
VAULT_PATH=bpm_core/develop \
|
|
425
|
+
pnpm typeorm migration:run
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
Required environment variables for direct Vault loading:
|
|
429
|
+
|
|
430
|
+
| Variable | Description |
|
|
431
|
+
| ---------------- | ----------------------------------- |
|
|
432
|
+
| `VAULT_HOST` | Vault HTTP base URL. |
|
|
433
|
+
| `VAULT_ACCOUNT` | Vault userpass account. |
|
|
434
|
+
| `VAULT_PASSWORD` | Vault userpass password. |
|
|
435
|
+
| `VAULT_PATH` | Vault KV path, defaults to develop. |
|
|
436
|
+
|
|
437
|
+
## Migrations
|
|
438
|
+
|
|
439
|
+
This package ships TypeORM migrations under `src/lib/migrations`.
|
|
440
|
+
|
|
441
|
+
For this repository:
|
|
442
|
+
|
|
443
|
+
```bash
|
|
444
|
+
pnpm migration:run
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
For an external host, import the class list instead of relying on a repository
|
|
448
|
+
source glob:
|
|
449
|
+
|
|
450
|
+
```ts
|
|
451
|
+
import { BPM_CORE_MIGRATIONS } from '@rytass/bpm-core-nestjs-module/migrations';
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
`buildBPMDataSourceOptions()`, `buildDataSourceOptionsFromVaultEnv()`, and
|
|
455
|
+
`buildTypeOrmModuleOptions()` use this exported migration list. Runtime
|
|
456
|
+
`TypeOrmModule` setup still keeps `migrationsRun: false`; run migrations
|
|
457
|
+
explicitly during deploy.
|
|
458
|
+
|
|
459
|
+
The first migration attempts to create required PostgreSQL extensions
|
|
460
|
+
(`uuid-ossp`, `ltree`) if they do not exist. Hosts that cannot grant
|
|
461
|
+
`CREATE EXTENSION` should pre-provision those extensions in the target database
|
|
462
|
+
before running BPM migrations. Schema selection comes from the TypeORM `schema`
|
|
463
|
+
option, so multi-schema hosts should run the same migration list once per BPM
|
|
464
|
+
schema/user pair.
|
|
465
|
+
|
|
466
|
+
Do not enable `synchronize` in production.
|
|
467
|
+
|
|
468
|
+
## Attachment Storage
|
|
469
|
+
|
|
470
|
+
By default, attachments use local storage under `.storage/attachments`. For
|
|
471
|
+
production, provide an `@rytass/storages` compatible adapter:
|
|
472
|
+
|
|
473
|
+
```ts
|
|
474
|
+
BPMRootModule.forRoot({
|
|
475
|
+
attachmentStorageProvider: {
|
|
476
|
+
provide: ATTACHMENT_STORAGE,
|
|
477
|
+
useFactory: (): AttachmentStorage => createYourStorageAdapter(),
|
|
478
|
+
},
|
|
479
|
+
authContextFactory: buildBPMAuthContextFromExecutionContext,
|
|
480
|
+
memberResolverProvider: {
|
|
481
|
+
provide: BPM_MEMBER_RESOLVER,
|
|
482
|
+
useClass: HostBPMMemberResolver,
|
|
483
|
+
},
|
|
484
|
+
});
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
Signed attachment URLs are served by BPM's attachment controller. Configure
|
|
488
|
+
`attachmentPublicBaseUrl`, `attachmentRoutePrefix`,
|
|
489
|
+
`attachmentSignedUrlSecret`, and `attachmentSignedUrlTtlSeconds` for production.
|
|
490
|
+
Set `attachmentStorageProviderId` when replacing local storage so attachment
|
|
491
|
+
metadata does not incorrectly say `local`.
|
|
492
|
+
|
|
493
|
+
`attachmentRoutePrefix` controls two things at the same time:
|
|
494
|
+
|
|
495
|
+
1. The path BPM bakes into signed URLs
|
|
496
|
+
(`${publicBaseUrl}${routePrefix}/:id/download`).
|
|
497
|
+
2. The Nest controller mount path. `AttachmentModule.forRoot` /
|
|
498
|
+
`forRootAsync` call `Reflect.defineMetadata(PATH_METADATA, ...)` on
|
|
499
|
+
`AttachmentController` so the controller actually serves on the same path
|
|
500
|
+
the signed URL points to.
|
|
501
|
+
|
|
502
|
+
The default is `/attachments`, matching the BPM controller's relative
|
|
503
|
+
declaration. BPM no longer assumes the host calls `setGlobalPrefix('api')`;
|
|
504
|
+
do not enable `setGlobalPrefix` on a BPM host. To expose the attachment
|
|
505
|
+
endpoint under a different prefix, set `attachmentRoutePrefix` (for example
|
|
506
|
+
`/internal/bpm/attachments`) — BPM rewrites both the controller path and the
|
|
507
|
+
signed URL accordingly. Alternative URL shaping should happen at a reverse
|
|
508
|
+
proxy (Nginx, Cloudflare, k8s ingress), not via Nest globalPrefix.
|
|
509
|
+
|
|
510
|
+
Because Nest reads controller path metadata synchronously at application
|
|
511
|
+
bootstrap, `attachmentRoutePrefix` must be supplied at module wiring time:
|
|
512
|
+
|
|
513
|
+
- `BPMRootModule.forRoot` reads `options.attachmentRoutePrefix` directly.
|
|
514
|
+
- `BPMRootModule.forRootAsync` exposes `attachmentRoutePrefix` at the
|
|
515
|
+
top-level (sibling of `useFactory`), not as part of the async factory
|
|
516
|
+
return.
|
|
517
|
+
- A process can only mount BPM under a single prefix. Multi-tenant hosts that
|
|
518
|
+
want different prefixes per tenant should run separate processes.
|
|
519
|
+
|
|
520
|
+
## Notifications and SLA
|
|
521
|
+
|
|
522
|
+
BPM creates in-app notifications by default. Email and webhook delivery are
|
|
523
|
+
disabled unless enough configuration is present or explicitly enabled.
|
|
524
|
+
|
|
525
|
+
The `auto` setting on `notificationEmailEnabled` only activates email delivery
|
|
526
|
+
when **all** of the following are non-empty strings:
|
|
527
|
+
|
|
528
|
+
- `notificationEmailSmtpHost`
|
|
529
|
+
- `notificationEmailSmtpPort`
|
|
530
|
+
- `notificationEmailSmtpUsername`
|
|
531
|
+
- `notificationEmailSmtpPassword`
|
|
532
|
+
- `notificationEmailFrom`
|
|
533
|
+
|
|
534
|
+
If any one of those is missing, email stays off even on `auto`. Webhook
|
|
535
|
+
`auto` requires both `notificationWebhookEndpointUrl` and
|
|
536
|
+
`notificationWebhookSigningSecret`.
|
|
537
|
+
|
|
538
|
+
`notificationTemplateEngine: 'handlebars'` is currently a reserved value; the
|
|
539
|
+
runtime template renderer still uses the built-in `simple` renderer regardless
|
|
540
|
+
of this setting. Leave it as `simple` until the Handlebars implementation is
|
|
541
|
+
wired.
|
|
542
|
+
|
|
543
|
+
Delivery and SLA schedulers are disabled by default. Enable them only in a
|
|
544
|
+
dedicated worker process or in a single-replica host that intentionally owns
|
|
545
|
+
background work:
|
|
546
|
+
|
|
547
|
+
```ts
|
|
548
|
+
BPMRootModule.forRoot({
|
|
549
|
+
notificationDeliverySchedulerEnabled: true,
|
|
550
|
+
notificationSlaSchedulerEnabled: true,
|
|
551
|
+
authContextFactory: buildBPMAuthContextFromExecutionContext,
|
|
552
|
+
memberResolverProvider: {
|
|
553
|
+
provide: BPM_MEMBER_RESOLVER,
|
|
554
|
+
useClass: HostBPMMemberResolver,
|
|
555
|
+
},
|
|
556
|
+
});
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
BPM claims pending delivery rows with `FOR UPDATE SKIP LOCKED` and records
|
|
560
|
+
SLA notifications with an idempotency index, but a dedicated worker is still
|
|
561
|
+
the recommended production topology.
|
|
562
|
+
|
|
563
|
+
Hosts can replace built-in SMTP and signed webhook dispatch by providing
|
|
564
|
+
`BPM_NOTIFICATION_DISPATCHER` from an imported host module. The dispatcher can
|
|
565
|
+
publish to an existing mail service, queue, tenant router, or event bus:
|
|
566
|
+
|
|
567
|
+
```ts
|
|
568
|
+
import { BPM_NOTIFICATION_DISPATCHER } from '@rytass/bpm-core-nestjs-module/notification';
|
|
569
|
+
|
|
570
|
+
@Module({
|
|
571
|
+
providers: [
|
|
572
|
+
{
|
|
573
|
+
provide: BPM_NOTIFICATION_DISPATCHER,
|
|
574
|
+
useClass: HostNotificationDispatcher,
|
|
575
|
+
},
|
|
576
|
+
],
|
|
577
|
+
exports: [BPM_NOTIFICATION_DISPATCHER],
|
|
578
|
+
})
|
|
579
|
+
export class HostNotificationModule {}
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
Workflow service tasks are a separate integration point from notification
|
|
583
|
+
delivery. `WEBHOOK` service-task nodes run inside the workflow engine and use
|
|
584
|
+
`BPM_WORKFLOW_SERVICE_TASK_DISPATCHER`. The default dispatcher sends a JSON
|
|
585
|
+
`POST` with `fetch`; wrapper apps can replace it when outbound workflow actions
|
|
586
|
+
must be signed, queued, audited, or routed through an internal integration
|
|
587
|
+
service.
|
|
588
|
+
|
|
589
|
+
`BPMRootModule.forRoot` / `forRootAsync` forward the host `imports` to the
|
|
590
|
+
internal `WorkflowEngineModule.forRoot`, so the dispatcher provider may use
|
|
591
|
+
`useFactory` plus `inject` to read host-side tokens such as Vault secrets or
|
|
592
|
+
shared integration bus instances. Providers do not have to live in a
|
|
593
|
+
`@Global()` module to be injectable from the dispatcher.
|
|
594
|
+
|
|
595
|
+
```ts
|
|
596
|
+
import { Injectable } from '@nestjs/common';
|
|
597
|
+
import {
|
|
598
|
+
BPMRootModule,
|
|
599
|
+
BPM_MEMBER_RESOLVER,
|
|
600
|
+
BPM_WORKFLOW_SERVICE_TASK_DISPATCHER,
|
|
601
|
+
BPMWorkflowServiceTaskDispatcher,
|
|
602
|
+
BPMWorkflowWebhookDispatchInput,
|
|
603
|
+
BPMWorkflowWebhookDispatchResult,
|
|
604
|
+
} from '@rytass/bpm-core-nestjs-module';
|
|
605
|
+
|
|
606
|
+
interface IntegrationBusResult {
|
|
607
|
+
readonly accepted: boolean;
|
|
608
|
+
readonly reason?: string;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
interface IntegrationBus {
|
|
612
|
+
enqueue(
|
|
613
|
+
topic: string,
|
|
614
|
+
payload: Readonly<Record<string, unknown>>,
|
|
615
|
+
): Promise<IntegrationBusResult>;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
@Injectable()
|
|
619
|
+
class HostWorkflowServiceTaskDispatcher implements BPMWorkflowServiceTaskDispatcher {
|
|
620
|
+
constructor(private readonly integrationBus: IntegrationBus) {}
|
|
621
|
+
|
|
622
|
+
async dispatchWebhook(
|
|
623
|
+
input: BPMWorkflowWebhookDispatchInput,
|
|
624
|
+
): Promise<BPMWorkflowWebhookDispatchResult> {
|
|
625
|
+
const result = await this.integrationBus.enqueue('bpm.workflow.webhook', {
|
|
626
|
+
headers: input.headers ?? {},
|
|
627
|
+
payload: input.payload,
|
|
628
|
+
url: input.url,
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
return {
|
|
632
|
+
ok: result.accepted,
|
|
633
|
+
status: result.accepted ? 202 : null,
|
|
634
|
+
error: result.accepted ? undefined : result.reason,
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
BPMRootModule.forRoot({
|
|
640
|
+
authContextFactory: buildBPMAuthContextFromExecutionContext,
|
|
641
|
+
memberResolverProvider: {
|
|
642
|
+
provide: BPM_MEMBER_RESOLVER,
|
|
643
|
+
useClass: HostBPMMemberResolver,
|
|
644
|
+
},
|
|
645
|
+
workflowServiceTaskDispatcherProvider: {
|
|
646
|
+
provide: BPM_WORKFLOW_SERVICE_TASK_DISPATCHER,
|
|
647
|
+
useClass: HostWorkflowServiceTaskDispatcher,
|
|
648
|
+
},
|
|
649
|
+
});
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
SLA timeout actions that change workflow state are disabled by default:
|
|
653
|
+
|
|
654
|
+
- `AUTO_APPROVE`
|
|
655
|
+
- `ESCALATE`
|
|
656
|
+
- `TERMINATE_INSTANCE`
|
|
657
|
+
|
|
658
|
+
Enable them only after the host application's business policy is explicit.
|
|
659
|
+
|
|
660
|
+
## Signatures
|
|
661
|
+
|
|
662
|
+
Decision signatures use HMAC-SHA256 and are chained through the previous
|
|
663
|
+
signature hash. Production hosts should provide a durable key provider and real
|
|
664
|
+
timestamp provider:
|
|
665
|
+
|
|
666
|
+
```ts
|
|
667
|
+
BPMRootModule.forRoot({
|
|
668
|
+
signatureCurrentKeyVersion: 2,
|
|
669
|
+
signatureKeyProvider: {
|
|
670
|
+
readKey: async (keyVersion: number): Promise<string | null> => readKeyFromKmsOrVault(keyVersion),
|
|
671
|
+
},
|
|
672
|
+
signatureTimestampProvider: {
|
|
673
|
+
createTimestampToken: async ({ signedAt, signedPayloadHash }): Promise<Buffer> => requestTimestampTokenFromTsa({ signedAt, signedPayloadHash }),
|
|
674
|
+
},
|
|
675
|
+
authContextFactory: buildBPMAuthContextFromExecutionContext,
|
|
676
|
+
memberResolverProvider: {
|
|
677
|
+
provide: BPM_MEMBER_RESOLVER,
|
|
678
|
+
useClass: HostBPMMemberResolver,
|
|
679
|
+
},
|
|
680
|
+
});
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
Keep old signature keys readable after rotation. Verification needs the key
|
|
684
|
+
version stored on each signature row.
|
|
685
|
+
|
|
686
|
+
Both `readKey` and `createTimestampToken` accept either a synchronous return
|
|
687
|
+
or a `Promise`; the example above uses async because production KMS / TSA
|
|
688
|
+
clients are typically network-bound. Returning a synchronous value is fine
|
|
689
|
+
for in-memory or local-file providers.
|
|
690
|
+
|
|
691
|
+
## GraphQL Surface
|
|
692
|
+
|
|
693
|
+
Importing `BPMRootModule` registers GraphQL resolvers for:
|
|
694
|
+
|
|
695
|
+
- Organization units, positions, memberships, manager resolution, and summary.
|
|
696
|
+
- Member profile lookup and member metadata cache inspection.
|
|
697
|
+
- Form definitions and form definition versions.
|
|
698
|
+
- Approval templates, template versions, categories, validation, and dry run.
|
|
699
|
+
- Workflow instances, tokens, tasks, task candidates, decisions, activity logs,
|
|
700
|
+
submit/process/approve/return/cancel/resubmit operations.
|
|
701
|
+
- Delegation rule CRUD and transfer support.
|
|
702
|
+
- Notifications, unread counts, preferences, and read status.
|
|
703
|
+
- Attachments, signed download URLs, and signed preview URLs.
|
|
704
|
+
- Decision signatures and signature-chain verification.
|
|
705
|
+
|
|
706
|
+
The schema is generated by NestJS GraphQL code-first decorators. Configure the
|
|
707
|
+
host `GraphQLModule` with `autoSchemaFile` if you want NestJS to generate the
|
|
708
|
+
schema at runtime.
|
|
709
|
+
|
|
710
|
+
## Shared Types
|
|
711
|
+
|
|
712
|
+
Workflow, form, condition, identity, organization, and status contracts live in
|
|
713
|
+
`@rytass/bpm-core-shared`.
|
|
714
|
+
|
|
715
|
+
```ts
|
|
716
|
+
import type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';
|
|
717
|
+
import type { FormSchema } from '@rytass/bpm-core-shared/form';
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
Use shared contracts when building UI clients or host-side integration tests.
|
|
721
|
+
|
|
722
|
+
## Import Paths
|
|
723
|
+
|
|
724
|
+
The package root is the canonical import path for common host-facing APIs.
|
|
725
|
+
Stable feature subpaths are also published for narrower imports such as
|
|
726
|
+
migrations or notification dispatcher tokens.
|
|
727
|
+
|
|
728
|
+
```ts
|
|
729
|
+
import {
|
|
730
|
+
AllExceptionsFilter,
|
|
731
|
+
BPMAdminGuard,
|
|
732
|
+
BPMAdminOnly,
|
|
733
|
+
BPMAuthenticated,
|
|
734
|
+
BPMAuthenticatedGuard,
|
|
735
|
+
BPMCurrentAuthContext,
|
|
736
|
+
BPMCurrentMemberId,
|
|
737
|
+
BPMDesignerGuard,
|
|
738
|
+
BPMDesignerOnly,
|
|
739
|
+
BPMRootModule,
|
|
740
|
+
buildTypeOrmModuleOptions,
|
|
741
|
+
createBPMMemberBaseResolverProvider,
|
|
742
|
+
} from '@rytass/bpm-core-nestjs-module';
|
|
743
|
+
|
|
744
|
+
import { BPM_CORE_MIGRATIONS } from '@rytass/bpm-core-nestjs-module/migrations';
|
|
745
|
+
import { BPM_NOTIFICATION_DISPATCHER } from '@rytass/bpm-core-nestjs-module/notification';
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
`AllExceptionsFilter` is the BPM-aware global exception filter the wrapper
|
|
749
|
+
app uses on its NestJS bootstrap; hosts that want consistent GraphQL/HTTP
|
|
750
|
+
error responses can call `app.useGlobalFilters(new AllExceptionsFilter())`.
|
|
751
|
+
|
|
752
|
+
Use root imports for module wiring, guards, options, and adapter helpers.
|
|
753
|
+
Feature subpaths are intended for narrow integration tokens or migration lists.
|
|
754
|
+
Do not treat internal domain services as the primary host API unless their
|
|
755
|
+
method contracts are explicitly documented.
|
|
756
|
+
|
|
757
|
+
Do not import from internal compiled paths such as
|
|
758
|
+
`@rytass/bpm-core-nestjs-module/src/lib/...`.
|
|
759
|
+
|
|
760
|
+
## Local Development
|
|
761
|
+
|
|
762
|
+
From this repository, use the wrapper app to run the backend and client:
|
|
763
|
+
|
|
764
|
+
```bash
|
|
765
|
+
pnpm install
|
|
766
|
+
pnpm demo:reset
|
|
767
|
+
pnpm api
|
|
768
|
+
pnpm client
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
`pnpm demo:reset` runs migrations before resetting and seeding develop data. Use
|
|
772
|
+
`pnpm migration:run` separately only when you need migrations without resetting
|
|
773
|
+
the wrapper-app seed scenario.
|
|
774
|
+
|
|
775
|
+
Default local service URLs:
|
|
776
|
+
|
|
777
|
+
- API: `http://localhost:17603`
|
|
778
|
+
- GraphQL: `http://localhost:17603/graphql`
|
|
779
|
+
- Client: `http://localhost:17602`
|
|
780
|
+
|
|
781
|
+
The normal local flow uses Vault-backed develop secrets. `docker compose` is not
|
|
782
|
+
required for local verification.
|
|
783
|
+
|
|
784
|
+
`pnpm demo:reset` is a repository wrapper-app command, not a package feature. It
|
|
785
|
+
resets the develop schema and seeds a Taiwan manufacturing scenario through
|
|
786
|
+
`apps/api/tools/reset-demo-data.ts`, including DB-backed test members in
|
|
787
|
+
`api_test_members`. Staging uses the same script through `pnpm staging:reset`
|
|
788
|
+
with `VAULT_PATH=bpm_core/staging`.
|
|
789
|
+
|
|
790
|
+
## Verification
|
|
791
|
+
|
|
792
|
+
Before publishing:
|
|
793
|
+
|
|
794
|
+
```bash
|
|
795
|
+
pnpm nx test bpm-core --runInBand
|
|
796
|
+
pnpm nx typecheck bpm-core
|
|
797
|
+
pnpm nx build bpm-core
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
Repository-wide checks:
|
|
801
|
+
|
|
802
|
+
```bash
|
|
803
|
+
pnpm typecheck
|
|
804
|
+
pnpm lint
|
|
805
|
+
pnpm test
|
|
806
|
+
pnpm build
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
## Publishing Checklist
|
|
810
|
+
|
|
811
|
+
1. Confirm package metadata in `libs/bpm-core/package.json`.
|
|
812
|
+
2. Confirm `@rytass/bpm-core-shared` is published at the required version.
|
|
813
|
+
3. Run `pnpm nx build bpm-core`.
|
|
814
|
+
4. Inspect `dist/libs/bpm-core/package.json`.
|
|
815
|
+
5. Confirm `dist/libs/bpm-core/README.md` is present.
|
|
816
|
+
6. Confirm `src/index.ts` exports every intended public API.
|
|
817
|
+
7. Publish from the built package directory:
|
|
818
|
+
|
|
819
|
+
```bash
|
|
820
|
+
cd dist/libs/bpm-core
|
|
821
|
+
npm publish --access public
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
## Production Notes
|
|
825
|
+
|
|
826
|
+
- Replace all local fallback secrets before production.
|
|
827
|
+
- Use a production storage adapter instead of local filesystem storage.
|
|
828
|
+
- Keep old signature keys available for verification after key rotation.
|
|
829
|
+
- Keep in-process schedulers disabled in API replicas unless a dedicated worker
|
|
830
|
+
is not available.
|
|
831
|
+
- Do not enable TypeORM `synchronize` in production.
|
|
832
|
+
- Ensure GraphQL auth context is available for protected operations.
|
|
833
|
+
- Run migrations before serving traffic with a new package version.
|
|
834
|
+
|
|
835
|
+
## License
|
|
836
|
+
|
|
837
|
+
MIT
|