@pattern-stack/codegen 0.10.1 → 0.12.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 +122 -0
- package/README.md +5 -5
- package/consumer-skills/codegen/SKILL.md +2 -2
- package/consumer-skills/{sync → integration}/SKILL.md +29 -29
- package/consumer-skills/{sync → integration}/audit-and-detection.md +22 -22
- package/consumer-skills/{sync → integration}/change-sources-and-sinks.md +60 -60
- package/consumer-skills/subsystems/SKILL.md +8 -8
- package/consumer-skills/subsystems/wiring-and-order.md +7 -7
- package/dist/runtime/base-classes/index.d.ts +4 -4
- package/dist/runtime/base-classes/index.js +35 -35
- package/dist/runtime/base-classes/index.js.map +1 -1
- package/dist/runtime/base-classes/{synced-entity-repository.d.ts → integrated-entity-repository.d.ts} +15 -15
- package/dist/runtime/base-classes/{synced-entity-repository.js → integrated-entity-repository.js} +21 -21
- package/dist/runtime/base-classes/integrated-entity-repository.js.map +1 -0
- package/dist/runtime/base-classes/{synced-entity-service.d.ts → integrated-entity-service.d.ts} +6 -6
- package/dist/runtime/base-classes/{synced-entity-service.js → integrated-entity-service.js} +4 -4
- package/dist/runtime/base-classes/integrated-entity-service.js.map +1 -0
- package/dist/runtime/base-classes/{sync-upsert-config.d.ts → integration-upsert-config.d.ts} +13 -13
- package/dist/runtime/base-classes/integration-upsert-config.js +1 -0
- package/dist/runtime/base-classes/{junction-sync-repository.d.ts → junction-integration-repository.d.ts} +11 -11
- package/dist/runtime/base-classes/{junction-sync-repository.js → junction-integration-repository.js} +15 -15
- package/dist/runtime/base-classes/junction-integration-repository.js.map +1 -0
- package/dist/runtime/subsystems/auth/auth-oauth-state.schema.js.map +1 -1
- package/dist/runtime/subsystems/auth/auth.module.d.ts +4 -4
- package/dist/runtime/subsystems/auth/auth.module.js +3 -3
- package/dist/runtime/subsystems/auth/auth.module.js.map +1 -1
- package/dist/runtime/subsystems/auth/auth.tokens.d.ts +8 -8
- package/dist/runtime/subsystems/auth/auth.tokens.js +6 -6
- package/dist/runtime/subsystems/auth/auth.tokens.js.map +1 -1
- package/dist/runtime/subsystems/auth/backends/state-store.drizzle-backend.js.map +1 -1
- package/dist/runtime/subsystems/auth/controllers/auth.controller.d.ts +2 -2
- package/dist/runtime/subsystems/auth/controllers/auth.controller.js +3 -3
- package/dist/runtime/subsystems/auth/controllers/auth.controller.js.map +1 -1
- package/dist/runtime/subsystems/auth/index.d.ts +3 -3
- package/dist/runtime/subsystems/auth/index.js +40 -40
- package/dist/runtime/subsystems/auth/index.js.map +1 -1
- package/dist/runtime/subsystems/auth/middleware/requester-context.js.map +1 -1
- package/dist/runtime/subsystems/auth/protocols/auth-strategy.d.ts +3 -3
- package/dist/runtime/subsystems/auth/protocols/{integration-store.d.ts → connection-store.d.ts} +20 -20
- package/dist/runtime/subsystems/auth/protocols/connection-store.js +1 -0
- package/dist/runtime/subsystems/auth/protocols/provider-strategy.d.ts +3 -3
- package/dist/runtime/subsystems/auth/runtime/{integration-broken.error.d.ts → connection-broken.error.d.ts} +5 -5
- package/dist/runtime/subsystems/auth/runtime/connection-broken.error.js +19 -0
- package/dist/runtime/subsystems/auth/runtime/connection-broken.error.js.map +1 -0
- package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.d.ts +10 -10
- package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.js +28 -28
- package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.js.map +1 -1
- package/dist/runtime/subsystems/auth/runtime/with-auth-retry.d.ts +1 -1
- package/dist/runtime/subsystems/auth/runtime/with-auth-retry.js +3 -3
- package/dist/runtime/subsystems/auth/runtime/with-auth-retry.js.map +1 -1
- package/dist/runtime/subsystems/index.d.ts +11 -7
- package/dist/runtime/subsystems/index.js +1041 -67
- package/dist/runtime/subsystems/index.js.map +1 -1
- package/dist/runtime/subsystems/{sync → integration}/build-change-source.d.ts +3 -3
- package/dist/runtime/subsystems/{sync → integration}/build-change-source.js +3 -3
- package/dist/runtime/subsystems/integration/build-change-source.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/deep-equal.differ.d.ts +2 -2
- package/dist/runtime/subsystems/{sync → integration}/deep-equal.differ.js +1 -1
- package/dist/runtime/subsystems/integration/deep-equal.differ.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/detection-config.schema.d.ts +3 -3
- package/dist/runtime/subsystems/{sync → integration}/detection-config.schema.js +1 -1
- package/dist/runtime/subsystems/integration/detection-config.schema.js.map +1 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.memory.d.ts +25 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.memory.js +34 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.memory.js.map +1 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.protocol.d.ts +53 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.protocol.js +13 -0
- package/dist/runtime/subsystems/integration/entity-change-source-registry.protocol.js.map +1 -0
- package/dist/runtime/subsystems/{sync/execute-sync.use-case.d.ts → integration/execute-integration.use-case.d.ts} +13 -13
- package/dist/runtime/subsystems/{sync/execute-sync.use-case.js → integration/execute-integration.use-case.js} +30 -30
- package/dist/runtime/subsystems/integration/execute-integration.use-case.js.map +1 -0
- package/dist/runtime/subsystems/integration/index.d.ts +30 -0
- package/dist/runtime/subsystems/{sync → integration}/index.js +206 -171
- package/dist/runtime/subsystems/integration/index.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-audit.schema.d.ts → integration/integration-audit.schema.d.ts} +64 -64
- package/dist/runtime/subsystems/{sync/sync-audit.schema.js → integration/integration-audit.schema.js} +47 -47
- package/dist/runtime/subsystems/integration/integration-audit.schema.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-change-source.protocol.d.ts → integration/integration-change-source.protocol.d.ts} +10 -10
- package/dist/runtime/subsystems/integration/integration-change-source.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-cursor-store.drizzle-backend.d.ts → integration/integration-cursor-store.drizzle-backend.d.ts} +1 -1
- package/dist/runtime/subsystems/{sync/sync-cursor-store.drizzle-backend.js → integration/integration-cursor-store.drizzle-backend.js} +65 -65
- package/dist/runtime/subsystems/integration/integration-cursor-store.drizzle-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-cursor-store.memory-backend.d.ts → integration/integration-cursor-store.memory-backend.d.ts} +6 -6
- package/dist/runtime/subsystems/{sync/sync-cursor-store.memory-backend.js → integration/integration-cursor-store.memory-backend.js} +5 -5
- package/dist/runtime/subsystems/integration/integration-cursor-store.memory-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-cursor-store.protocol.d.ts → integration/integration-cursor-store.protocol.d.ts} +13 -13
- package/dist/runtime/subsystems/integration/integration-cursor-store.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-errors.d.ts → integration/integration-errors.d.ts} +2 -2
- package/dist/runtime/subsystems/{sync/sync-errors.js → integration/integration-errors.js} +3 -3
- package/dist/runtime/subsystems/integration/integration-errors.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-field-diff.protocol.d.ts → integration/integration-field-diff.protocol.d.ts} +2 -2
- package/dist/runtime/subsystems/{sync/sync-field-diff.protocol.js → integration/integration-field-diff.protocol.js} +2 -2
- package/dist/runtime/subsystems/integration/integration-field-diff.protocol.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-loopback.protocol.d.ts → integration/integration-loopback.protocol.d.ts} +2 -2
- package/dist/runtime/subsystems/integration/integration-loopback.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-middleware.protocol.d.ts → integration/integration-middleware.protocol.d.ts} +5 -5
- package/dist/runtime/subsystems/integration/integration-middleware.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-run-recorder.drizzle-backend.d.ts → integration/integration-run-recorder.drizzle-backend.d.ts} +5 -5
- package/dist/runtime/subsystems/{sync/sync-run-recorder.drizzle-backend.js → integration/integration-run-recorder.drizzle-backend.js} +73 -73
- package/dist/runtime/subsystems/integration/integration-run-recorder.drizzle-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-run-recorder.memory-backend.d.ts → integration/integration-run-recorder.memory-backend.d.ts} +15 -15
- package/dist/runtime/subsystems/{sync/sync-run-recorder.memory-backend.js → integration/integration-run-recorder.memory-backend.js} +11 -11
- package/dist/runtime/subsystems/integration/integration-run-recorder.memory-backend.js.map +1 -0
- package/dist/runtime/subsystems/{sync/sync-run-recorder.protocol.d.ts → integration/integration-run-recorder.protocol.d.ts} +25 -25
- package/dist/runtime/subsystems/integration/integration-run-recorder.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync-sink.protocol.d.ts → integration/integration-sink.protocol.d.ts} +5 -5
- package/dist/runtime/subsystems/integration/integration-sink.protocol.js +1 -0
- package/dist/runtime/subsystems/{sync/sync.module.d.ts → integration/integration.module.d.ts} +24 -24
- package/dist/runtime/subsystems/{sync/sync.module.js → integration/integration.module.js} +132 -132
- package/dist/runtime/subsystems/integration/integration.module.js.map +1 -0
- package/dist/runtime/subsystems/integration/integration.tokens.d.ts +60 -0
- package/dist/runtime/subsystems/integration/integration.tokens.js +20 -0
- package/dist/runtime/subsystems/integration/integration.tokens.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/loopback.middleware.d.ts +5 -5
- package/dist/runtime/subsystems/{sync → integration}/loopback.middleware.js +1 -1
- package/dist/runtime/subsystems/integration/loopback.middleware.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/poll-change-source.d.ts +5 -5
- package/dist/runtime/subsystems/{sync → integration}/poll-change-source.js +1 -1
- package/dist/runtime/subsystems/integration/poll-change-source.js.map +1 -0
- package/dist/runtime/subsystems/{sync → integration}/webhook-change-source.d.ts +5 -5
- package/dist/runtime/subsystems/{sync → integration}/webhook-change-source.js +1 -1
- package/dist/runtime/subsystems/integration/webhook-change-source.js.map +1 -0
- package/dist/runtime/subsystems/jobs/job-worker.module.d.ts +1 -1
- package/dist/runtime/subsystems/observability/index.d.ts +4 -4
- package/dist/runtime/subsystems/observability/index.js +11 -11
- package/dist/runtime/subsystems/observability/index.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.module.d.ts +2 -2
- package/dist/runtime/subsystems/observability/observability.module.js +11 -11
- package/dist/runtime/subsystems/observability/observability.module.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.protocol.d.ts +11 -11
- package/dist/runtime/subsystems/observability/observability.service.d.ts +6 -6
- package/dist/runtime/subsystems/observability/observability.service.js +11 -11
- package/dist/runtime/subsystems/observability/observability.service.js.map +1 -1
- package/dist/runtime/subsystems/observability/observability.tokens.d.ts +1 -1
- package/dist/runtime/subsystems/observability/observability.tokens.js.map +1 -1
- package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.d.ts +3 -3
- package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.js.map +1 -1
- package/dist/runtime/subsystems/observability/reporters/index.d.ts +3 -3
- package/dist/runtime/subsystems/observability/reporters/index.js.map +1 -1
- package/dist/src/cli/index.js +1336 -376
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/index.d.ts +70 -22
- package/dist/src/index.js +290 -194
- package/dist/src/index.js.map +1 -1
- package/examples/auth-integrations/README.md +32 -32
- package/examples/auth-integrations/definitions/entities/{integration.yaml → connection.yaml} +10 -10
- package/examples/auth-integrations/runtime/{integrations/adapters/integration-grant-sink.adapter.ts → connections/adapters/connection-grant-sink.adapter.ts} +7 -7
- package/examples/auth-integrations/runtime/{integrations/adapters/integration-reader.adapter.ts → connections/adapters/connection-reader.adapter.ts} +10 -10
- package/examples/auth-integrations/runtime/{integrations/adapters/integration-token-writer.adapter.ts → connections/adapters/connection-token-writer.adapter.ts} +11 -11
- package/examples/auth-integrations/runtime/connections/connections-auth.module.ts +81 -0
- package/examples/auth-integrations/runtime/{integrations/facade/integrations.service.ts → connections/facade/connections.service.ts} +35 -35
- package/examples/auth-integrations/runtime/{integrations → connections}/oauth/use-cases/create-or-update-from-oauth-grant.use-case.ts +11 -11
- package/examples/auth-integrations/runtime/{integrations/oauth/use-cases/disconnect-integration.use-case.ts → connections/oauth/use-cases/disconnect-connection.use-case.ts} +6 -6
- package/examples/auth-integrations/runtime/connections/oauth/use-cases/list-user-connections.use-case.ts +21 -0
- package/examples/auth-integrations/runtime/connections/oauth/use-cases/mark-connection-requires-reauth.use-case.ts +21 -0
- package/package.json +9 -1
- package/runtime/base-classes/index.ts +8 -8
- package/runtime/base-classes/{synced-entity-repository.ts → integrated-entity-repository.ts} +36 -36
- package/runtime/base-classes/{synced-entity-service.ts → integrated-entity-service.ts} +6 -6
- package/runtime/base-classes/{sync-upsert-config.ts → integration-upsert-config.ts} +12 -12
- package/runtime/base-classes/{junction-sync-repository.ts → junction-integration-repository.ts} +28 -28
- package/runtime/subsystems/auth/auth-oauth-state.schema.ts +1 -1
- package/runtime/subsystems/auth/auth.module.ts +4 -4
- package/runtime/subsystems/auth/auth.tokens.ts +7 -7
- package/runtime/subsystems/auth/controllers/auth.controller.ts +7 -7
- package/runtime/subsystems/auth/index.ts +19 -19
- package/runtime/subsystems/auth/protocols/auth-strategy.ts +3 -3
- package/runtime/subsystems/auth/protocols/{integration-store.ts → connection-store.ts} +19 -19
- package/runtime/subsystems/auth/protocols/provider-strategy.ts +2 -2
- package/runtime/subsystems/auth/runtime/{integration-broken.error.ts → connection-broken.error.ts} +5 -5
- package/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.ts +35 -35
- package/runtime/subsystems/auth/runtime/with-auth-retry.ts +3 -3
- package/runtime/subsystems/index.ts +26 -11
- package/runtime/subsystems/{sync → integration}/build-change-source.ts +3 -3
- package/runtime/subsystems/{sync → integration}/deep-equal.differ.ts +7 -7
- package/runtime/subsystems/{sync → integration}/detection-config.schema.ts +3 -3
- package/runtime/subsystems/integration/entity-change-source-registry.memory.ts +40 -0
- package/runtime/subsystems/integration/entity-change-source-registry.protocol.ts +59 -0
- package/runtime/subsystems/{sync/execute-sync.use-case.ts → integration/execute-integration.use-case.ts} +40 -40
- package/runtime/subsystems/{sync → integration}/index.ts +56 -47
- package/runtime/subsystems/{sync/sync-audit.schema.ts → integration/integration-audit.schema.ts} +61 -61
- package/runtime/subsystems/{sync/sync-change-source.protocol.ts → integration/integration-change-source.protocol.ts} +9 -9
- package/runtime/subsystems/{sync/sync-cursor-store.drizzle-backend.ts → integration/integration-cursor-store.drizzle-backend.ts} +30 -30
- package/runtime/subsystems/{sync/sync-cursor-store.memory-backend.ts → integration/integration-cursor-store.memory-backend.ts} +9 -9
- package/runtime/subsystems/{sync/sync-cursor-store.protocol.ts → integration/integration-cursor-store.protocol.ts} +13 -13
- package/runtime/subsystems/{sync/sync-errors.ts → integration/integration-errors.ts} +3 -3
- package/runtime/subsystems/{sync/sync-field-diff.protocol.ts → integration/integration-field-diff.protocol.ts} +2 -2
- package/runtime/subsystems/{sync/sync-loopback.protocol.ts → integration/integration-loopback.protocol.ts} +2 -2
- package/runtime/subsystems/{sync/sync-middleware.protocol.ts → integration/integration-middleware.protocol.ts} +6 -6
- package/runtime/subsystems/{sync/sync-run-recorder.drizzle-backend.ts → integration/integration-run-recorder.drizzle-backend.ts} +39 -39
- package/runtime/subsystems/{sync/sync-run-recorder.memory-backend.ts → integration/integration-run-recorder.memory-backend.ts} +23 -23
- package/runtime/subsystems/{sync/sync-run-recorder.protocol.ts → integration/integration-run-recorder.protocol.ts} +25 -25
- package/runtime/subsystems/{sync/sync-sink.protocol.ts → integration/integration-sink.protocol.ts} +4 -4
- package/runtime/subsystems/{sync/sync.module.ts → integration/integration.module.ts} +48 -48
- package/runtime/subsystems/integration/integration.tokens.ts +63 -0
- package/runtime/subsystems/{sync → integration}/loopback.middleware.ts +5 -5
- package/runtime/subsystems/{sync → integration}/poll-change-source.ts +7 -7
- package/runtime/subsystems/{sync → integration}/webhook-change-source.ts +7 -7
- package/runtime/subsystems/observability/index.ts +1 -1
- package/runtime/subsystems/observability/observability.module.ts +2 -2
- package/runtime/subsystems/observability/observability.protocol.ts +11 -11
- package/runtime/subsystems/observability/observability.service.ts +13 -13
- package/runtime/subsystems/observability/observability.tokens.ts +1 -1
- package/src/patterns/library/index.ts +4 -4
- package/src/patterns/library/{synced.pattern.ts → integrated.pattern.ts} +12 -12
- package/src/patterns/library/junction.pattern.ts +1 -1
- package/src/patterns/pattern-definition.ts +3 -3
- package/templates/entity/new/backend/modules/core/{sync-source.ejs.t → integration-source.ejs.t} +6 -6
- package/templates/entity/new/clean-lite-ps/entity.ejs.t +12 -3
- package/templates/entity/new/clean-lite-ps/module.ejs.t +1 -1
- package/templates/entity/new/clean-lite-ps/prompt-extension.js +243 -60
- package/templates/entity/new/clean-lite-ps/repository.ejs.t +27 -27
- package/templates/entity/new/frontend/collections/collection.ejs.t +26 -1
- package/templates/entity/new/frontend/collections/collections-base.ejs.t +11 -0
- package/templates/entity/new/frontend/entity/combined.ejs.t +31 -1
- package/templates/entity/new/prompt.js +27 -15
- package/templates/junction/new/entity.ejs.t +1 -1
- package/templates/junction/new/prompt.js +24 -24
- package/templates/junction/new/repository.ejs.t +19 -19
- package/templates/subsystem/auth/auth-oauth-state.schema.ejs.t +2 -2
- package/templates/subsystem/auth-config/prompt.js +1 -1
- package/templates/subsystem/auth-integrations/app-module-hook.ejs.t +5 -5
- package/templates/subsystem/bridge/prompt.js +1 -1
- package/templates/subsystem/integration/integration-audit.schema.ejs.t +192 -0
- package/templates/subsystem/{sync → integration}/prompt.js +12 -12
- package/templates/subsystem/{sync-config/codegen-config-sync-block.ejs.t → integration-config/codegen-config-integration-block.ejs.t} +7 -7
- package/templates/subsystem/integration-config/prompt.js +22 -0
- package/templates/subsystem/jobs/worker.ejs.t +2 -2
- package/templates/subsystem/observability/main-hook.ejs.t +1 -1
- package/templates/subsystem/observability/prompt.js +1 -1
- package/templates/subsystem/openapi-config/prompt.js +1 -1
- package/dist/runtime/base-classes/junction-sync-repository.js.map +0 -1
- package/dist/runtime/base-classes/sync-upsert-config.js +0 -1
- package/dist/runtime/base-classes/synced-entity-repository.js.map +0 -1
- package/dist/runtime/base-classes/synced-entity-service.js.map +0 -1
- package/dist/runtime/subsystems/auth/protocols/integration-store.js +0 -1
- package/dist/runtime/subsystems/auth/runtime/integration-broken.error.js +0 -19
- package/dist/runtime/subsystems/auth/runtime/integration-broken.error.js.map +0 -1
- package/dist/runtime/subsystems/sync/build-change-source.js.map +0 -1
- package/dist/runtime/subsystems/sync/deep-equal.differ.js.map +0 -1
- package/dist/runtime/subsystems/sync/detection-config.schema.js.map +0 -1
- package/dist/runtime/subsystems/sync/execute-sync.use-case.js.map +0 -1
- package/dist/runtime/subsystems/sync/index.d.ts +0 -28
- package/dist/runtime/subsystems/sync/index.js.map +0 -1
- package/dist/runtime/subsystems/sync/loopback.middleware.js.map +0 -1
- package/dist/runtime/subsystems/sync/poll-change-source.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-audit.schema.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-change-source.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-cursor-store.drizzle-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-cursor-store.memory-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-cursor-store.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-errors.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-field-diff.protocol.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-loopback.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-middleware.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-run-recorder.drizzle-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-run-recorder.memory-backend.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync-run-recorder.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync-sink.protocol.js +0 -1
- package/dist/runtime/subsystems/sync/sync.module.js.map +0 -1
- package/dist/runtime/subsystems/sync/sync.tokens.d.ts +0 -47
- package/dist/runtime/subsystems/sync/sync.tokens.js +0 -18
- package/dist/runtime/subsystems/sync/sync.tokens.js.map +0 -1
- package/dist/runtime/subsystems/sync/webhook-change-source.js.map +0 -1
- package/examples/auth-integrations/runtime/integrations/integrations-auth.module.ts +0 -81
- package/examples/auth-integrations/runtime/integrations/oauth/use-cases/list-user-integrations.use-case.ts +0 -21
- package/examples/auth-integrations/runtime/integrations/oauth/use-cases/mark-integration-requires-reauth.use-case.ts +0 -21
- package/runtime/subsystems/sync/sync.tokens.ts +0 -49
- package/templates/entity/new/backend/modules/core/sync-source.providers.ejs.t +0 -18
- package/templates/subsystem/sync/sync-audit.schema.ejs.t +0 -192
- package/templates/subsystem/sync-config/prompt.js +0 -22
- /package/dist/runtime/base-classes/{sync-upsert-config.js.map → integration-upsert-config.js.map} +0 -0
- /package/dist/runtime/subsystems/auth/protocols/{integration-store.js.map → connection-store.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-change-source.protocol.js.map → integration/integration-change-source.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-cursor-store.protocol.js.map → integration/integration-cursor-store.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-loopback.protocol.js.map → integration/integration-loopback.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-middleware.protocol.js.map → integration/integration-middleware.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-run-recorder.protocol.js.map → integration/integration-run-recorder.protocol.js.map} +0 -0
- /package/dist/runtime/subsystems/{sync/sync-sink.protocol.js.map → integration/integration-sink.protocol.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,128 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.12.0] — 2026-05-31
|
|
8
|
+
|
|
9
|
+
Integration codegen retarget (RFC-0001): a **provider/adapter/surface** model
|
|
10
|
+
for integration codegen, plus a **surface-package framework**. Additive over
|
|
11
|
+
0.11.0 — new declarative inputs and emitted artifacts; existing entity codegen
|
|
12
|
+
is unchanged. The one breaking item (the ADR-033.2 per-entity provider tuples)
|
|
13
|
+
has no consumers. Consumers adopt by adding `definitions/providers/*.yaml` and
|
|
14
|
+
regenerating. Ships alongside four independently-versioned **surface packages**
|
|
15
|
+
(`@pattern-stack/codegen-{crm,calendar,mail,transcript}`) publishing fresh at
|
|
16
|
+
`0.1.0`.
|
|
17
|
+
|
|
18
|
+
### ⚠ BREAKING CHANGES
|
|
19
|
+
|
|
20
|
+
- **ADR-033.2 per-entity provider tuples removed.** The
|
|
21
|
+
`<entity>-integration-source.providers.ts` emission (`<ENTITY>_PROVIDERS`
|
|
22
|
+
const + `<Entity>Provider` type) is deleted. Its replacement is the
|
|
23
|
+
surface-scoped, codegen-owned typed view at
|
|
24
|
+
`src/integrations/<surface>/types.generated.ts` (`<Surface>Provider` /
|
|
25
|
+
`<Surface>Entity` unions + a `(provider, entity)` validity map) — a single
|
|
26
|
+
source of provider truth. ADR-033.2 is superseded by RFC-0001. No published
|
|
27
|
+
consumers depend on the tuples.
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- **Track C — surface-package framework (ADR-036).** First-class L2 *surface
|
|
32
|
+
packages* shipping type-shaped ports + DI tokens + an L3 composing port per
|
|
33
|
+
integration surface:
|
|
34
|
+
- **L1** — `IEntityChangeSourceRegistry` (entity-keyed change-source
|
|
35
|
+
resolver) + `MemoryEntityChangeSourceRegistry` + the
|
|
36
|
+
`ENTITY_CHANGE_SOURCE_REGISTRY` token, in the integration subsystem;
|
|
37
|
+
exported across the package boundary via `@pattern-stack/codegen/subsystems`.
|
|
38
|
+
- **`@pattern-stack/codegen-crm`** — L2 CRM ports (`IFieldDefinitionReader`,
|
|
39
|
+
`IPicklistReader`, `IAssociationReader`), the `CrmCapabilities` descriptor,
|
|
40
|
+
and the L3 entity-agnostic **`CrmPort`** composing port + `assertCrmAdapter`
|
|
41
|
+
conformance helper (on the `/testing` subpath).
|
|
42
|
+
- **`@pattern-stack/codegen-{calendar,mail,transcript}`** — incremental-read
|
|
43
|
+
interaction surfaces (`CalendarPort` / `MailPort` / `TranscriptPort`,
|
|
44
|
+
canonical types, capability descriptors). Independently versioned (`0.1.0`).
|
|
45
|
+
- **Track D — provider/adapter integration codegen (RFC-0001).**
|
|
46
|
+
- `definitions/providers/<provider>.yaml` — providers as first-class
|
|
47
|
+
declarative artifacts (slug, auth strategy, client, surfaces); Zod schema +
|
|
48
|
+
validator with a **pre-flight import-path check** (a missing
|
|
49
|
+
strategy/client export fails `cdp gen`, not NestJS boot), surface
|
|
50
|
+
cross-check, and slug-uniqueness.
|
|
51
|
+
- Emits, per provider × surface: a `<provider>.provider.module.ts`, an
|
|
52
|
+
**emit-once** `<provider>-<surface>.adapter.ts` scaffold (sentinel-guarded,
|
|
53
|
+
author-owned after first emit), fully codegen-owned adapter modules +
|
|
54
|
+
barrels, a per-surface registry (`<SURFACE>_ADAPTER_CONTRIBUTIONS` →
|
|
55
|
+
`<SURFACE>_ENTITY_SOURCES`, folding into the L1 registry), and the
|
|
56
|
+
`types.generated.ts` typed view.
|
|
57
|
+
- Optional entity-YAML **`surface:`** field — the declarative input the
|
|
58
|
+
provider/adapter emission groups entities by.
|
|
59
|
+
- **`context:` output-folder grouping (#403).** An optional top-level entity
|
|
60
|
+
`context:` nests its generated module folder under that segment
|
|
61
|
+
(`<modules>/<context>/<plural>/`); no context → flat (byte-identical to
|
|
62
|
+
before).
|
|
63
|
+
- **Multi-package release.** `just publish` publishes the root plus every
|
|
64
|
+
opted-in `packages/*` (those declaring `publishConfig.access: public`) at its
|
|
65
|
+
own independent version, skipping versions already on npm.
|
|
66
|
+
|
|
67
|
+
## [0.11.0] — 2026-05-30
|
|
68
|
+
|
|
69
|
+
Vocabulary rename per **ADR-0005 (swe-brain `.ai-docs/decisions/ADR-0005-rename-sync-to-integration.md`)**:
|
|
70
|
+
the data-movement domain `sync` → `integration` (reserving "sync" for
|
|
71
|
+
ElectricSQL-style replication), the `Synced` entity family → `Integrated`, and
|
|
72
|
+
the authenticated vendor-link `IntegrationStore` → `ConnectionStore`. This is a
|
|
73
|
+
clean break — there are no compat shims or deprecated aliases; consumers
|
|
74
|
+
migrate by **regenerating** off the renamed substrate (codegen owns the
|
|
75
|
+
physical/structural names).
|
|
76
|
+
|
|
77
|
+
### ⚠ BREAKING CHANGES
|
|
78
|
+
|
|
79
|
+
- **Integration engine (`sync` → `integration`).**
|
|
80
|
+
- `SyncModule` → `IntegrationModule` (`.forRoot({ backend, multiTenant? })`);
|
|
81
|
+
`ExecuteSyncUseCase` → `ExecuteIntegrationUseCase`.
|
|
82
|
+
- Tokens `SYNC_*` → `INTEGRATION_*` (cursor store, run recorder, field
|
|
83
|
+
differ, change source, sink, multi-tenant flag, module options).
|
|
84
|
+
- Protocols/ports/recorders/cursor-stores/errors `sync-*` → `integration-*`;
|
|
85
|
+
`runtime/subsystems/sync/**` → `runtime/subsystems/integration/**`.
|
|
86
|
+
- Tables `sync_runs` / `sync_run_items` / `sync_subscriptions` →
|
|
87
|
+
`integration_runs` / `integration_run_items` / `integration_subscriptions`;
|
|
88
|
+
cursor column `last_sync_at` → `last_integration_at`.
|
|
89
|
+
- Entity-YAML config block `sync:` → `integration:` (incl. `sync.inbound` →
|
|
90
|
+
`integration.inbound`); the per-entity `*-sync-source.module.ts` codegen
|
|
91
|
+
output → `*-integration-source.module.ts`.
|
|
92
|
+
- CLI: `codegen subsystem install sync` → `… install integration`; the
|
|
93
|
+
`/sync` skill → `/integration`.
|
|
94
|
+
- **`Synced` entity family → `Integrated`.**
|
|
95
|
+
- `SyncedEntityRepository` / `SyncedEntityService` → `IntegratedEntityRepository`
|
|
96
|
+
/ `IntegratedEntityService`; `SyncUpsertConfig` → `IntegrationUpsertConfig`;
|
|
97
|
+
`syncUpsertOne`/`syncUpsert`/`syncConfig`/`SyncFkResolver` →
|
|
98
|
+
`integrationUpsertOne`/`integrationUpsert`/`integrationConfig`/`IntegrationFkResolver`;
|
|
99
|
+
`junction-sync-repository.ts` → `junction-integration-repository.ts`.
|
|
100
|
+
- YAML `pattern: Synced` → `pattern: Integrated`.
|
|
101
|
+
- **Auth vendor-link `integration` → `connection`.**
|
|
102
|
+
- `IntegrationStore` ports → `ConnectionStore`:
|
|
103
|
+
`IIntegrationReader`/`IIntegrationTokenWriter`/`IIntegrationGrantSink` →
|
|
104
|
+
`IConnection*`; `DecryptedIntegration` → `DecryptedConnection`;
|
|
105
|
+
`IntegrationGrantInput`/`IntegrationTokenUpdate` → `Connection*`;
|
|
106
|
+
`IntegrationBrokenError` → `ConnectionBrokenError`; DI tokens
|
|
107
|
+
`AUTH_INTEGRATION_*` → `AUTH_CONNECTION_*`.
|
|
108
|
+
- Engine FK `integration_subscriptions.integration_id` → `connection_id`
|
|
109
|
+
(the column references the connected account/instance — a *connection*;
|
|
110
|
+
the table name stays `integration_subscriptions`).
|
|
111
|
+
- The `examples/auth-integrations` starter is fully renamed to the connection
|
|
112
|
+
vocabulary: `connection.yaml` entity (table `connections`),
|
|
113
|
+
`ConnectionsService`, `ConnectionsAuthModule`, `Connection*Adapter`,
|
|
114
|
+
vendored under `<modules>/connections/`. The `auth-integrations` subsystem
|
|
115
|
+
**install command** keeps its name.
|
|
116
|
+
|
|
117
|
+
### Preserved (NOT renamed)
|
|
118
|
+
|
|
119
|
+
- The CLI imperative **verb** `sync` in app-level event names
|
|
120
|
+
(`crm_sync_started`, `webhook_outbound_contact_sync`).
|
|
121
|
+
- ElectricSQL `frontend.sync` collection config (replication sense).
|
|
122
|
+
|
|
123
|
+
### Migration
|
|
124
|
+
|
|
125
|
+
No shims. Re-vendor the runtime (`codegen update`) and **regenerate** entities/
|
|
126
|
+
subsystems off the renamed names; update app code that references the renamed
|
|
127
|
+
symbols/tokens/tables/config keys. See ADR-0005 (swe-brain `.ai-docs/decisions/ADR-0005-rename-sync-to-integration.md`).
|
|
128
|
+
|
|
7
129
|
## [0.10.1] — 2026-05-28
|
|
8
130
|
|
|
9
131
|
Dogfood fixes found wiring `@pattern-stack/codegen@0.10.0` into a second
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ entity:
|
|
|
23
23
|
name: contact
|
|
24
24
|
plural: contacts
|
|
25
25
|
table: contacts
|
|
26
|
-
pattern:
|
|
26
|
+
pattern: Integrated # Integrated | Activity | Metadata | Knowledge | Base (or app-defined)
|
|
27
27
|
|
|
28
28
|
fields:
|
|
29
29
|
email:
|
|
@@ -94,7 +94,7 @@ codegen subsystem install events # domain event bus (transactional outbox)
|
|
|
94
94
|
codegen subsystem install jobs # background job queue (pg-boss pattern)
|
|
95
95
|
codegen subsystem install cache # key-value cache with TTL
|
|
96
96
|
codegen subsystem install storage # file storage (local filesystem)
|
|
97
|
-
codegen subsystem install
|
|
97
|
+
codegen subsystem install integration # external-system integration engine (IChangeSource + orchestrator + audit log)
|
|
98
98
|
codegen subsystem install bridge # event-to-job bridge (durable async fanout via @JobHandler.triggers)
|
|
99
99
|
codegen subsystem install openapi-config # OpenAPI/Swagger — Zod DTOs as /docs-json + Swagger UI. See docs/CONSUMER-SETUP.md §OpenAPI
|
|
100
100
|
codegen subsystem install auth # OAuth integration auth (AuthModule + ports + state store + AuthController)
|
|
@@ -144,7 +144,7 @@ Families provide pre-built base classes with domain-specific query patterns:
|
|
|
144
144
|
|
|
145
145
|
| Family | When to Use | Key Methods |
|
|
146
146
|
|--------|-------------|-------------|
|
|
147
|
-
| `
|
|
147
|
+
| `integrated` | externally-integrated entities (contacts, accounts) | `findByExternalId`, `integrationUpsert`, `findAllByUserId` |
|
|
148
148
|
| `activity` | Time-based events (emails, calls, meetings) | `findByDateRange`, `findRecentByOpportunityId` |
|
|
149
149
|
| `metadata` | Key-value data (tags, custom fields) | `findByEntityIdAndType`, `upsertMany` |
|
|
150
150
|
| `knowledge` | Vector-searchable content | Stub (needs pgvector) |
|
|
@@ -163,9 +163,9 @@ queries:
|
|
|
163
163
|
- by: [user_id, status] # → FindContactByUserIdAndStatusUseCase (compound)
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
-
##
|
|
166
|
+
## Integration Detection (`detection:` block)
|
|
167
167
|
|
|
168
|
-
Entities that participate in the
|
|
168
|
+
Entities that participate in the integration subsystem may declare a `detection:` block describing how upstream changes are detected. The block is parsed by the canonical `DetectionConfigSchema` shipped from `runtime/subsystems/integration` — primitives (`PollChangeSource<T>`, `WebhookChangeSource<T>`) and the per-entity factory module emitted by codegen consume the same parsed shape, so YAML and runtime stay in lockstep (ADR-033, epic #226).
|
|
169
169
|
|
|
170
170
|
```yaml
|
|
171
171
|
detection:
|
|
@@ -7,7 +7,7 @@ description: >-
|
|
|
7
7
|
the `codegen` (aka `cdp`) CLI, install or wire an infrastructure subsystem, or
|
|
8
8
|
refresh the project after a package upgrade. This is the entry-point router;
|
|
9
9
|
it points at the focused `entities`, `subsystems`, `jobs`, `events`, `bridge`,
|
|
10
|
-
and `
|
|
10
|
+
and `integration` skills for deep work.
|
|
11
11
|
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
|
|
12
12
|
user-invocable: false
|
|
13
13
|
---
|
|
@@ -53,7 +53,7 @@ generation run the two barrels are rewritten and you wire them into
|
|
|
53
53
|
| Write a background `@JobHandler`, configure pools, set concurrency/ordering | the `jobs` skill |
|
|
54
54
|
| Author a domain event, publish via the outbox, use the typed event bus | the `events` skill |
|
|
55
55
|
| React to an event with a durable async job (the event-to-job bridge) | the `bridge` skill |
|
|
56
|
-
| Pull/push data from an external system (`IChangeSource` / `
|
|
56
|
+
| Pull/push data from an external system (`IChangeSource` / `IIntegrationSink`) | the `integration` skill |
|
|
57
57
|
|
|
58
58
|
## CLI quick reference
|
|
59
59
|
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: Load when integrating an external system (CRM, billing, etc.) in a project that ran `codegen subsystem install
|
|
2
|
+
name: integration
|
|
3
|
+
description: Load when integrating an external system (CRM, billing, etc.) in a project that ran `codegen subsystem install integration`. Triggers include implementing `IChangeSource<T>` for a provider; writing an `IIntegrationSink<T>`; registering `IntegrationModule.forRoot(...)` in `app.module.ts`; building a per-entity feature module that binds the change source, sink, and `ExecuteIntegrationUseCase`; declaring a `detection:` block in entity YAML; querying the `integration_runs` / `integration_run_items` audit log or the structured `changed_fields` jsonb; or wiring cursor persistence, diffing, and multi-tenancy.
|
|
4
4
|
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
|
|
5
5
|
user-invocable: false
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
<!-- managed by @pattern-stack/codegen — re-run `codegen skills install` to refresh. Edit the package source, not this vendored copy. -->
|
|
9
9
|
|
|
10
|
-
#
|
|
10
|
+
# Integration Subsystem
|
|
11
11
|
|
|
12
|
-
The
|
|
13
|
-
app. One orchestrator — `
|
|
12
|
+
The integration subsystem is a generic external-system integration engine for your
|
|
13
|
+
app. One orchestrator — `ExecuteIntegrationUseCase<T>` — runs *every* integration in
|
|
14
14
|
your codebase. You write per-provider detection code against a single port
|
|
15
15
|
(`IChangeSource<T>`) and per-entity write code against a single sink
|
|
16
|
-
(`
|
|
16
|
+
(`IIntegrationSink<T>`). Everything else — cursor persistence, field diffing,
|
|
17
17
|
per-record audit, run lifecycle — is provided by the subsystem.
|
|
18
18
|
|
|
19
|
-
You opt in with `codegen subsystem install
|
|
20
|
-
into `<paths.subsystems>/
|
|
21
|
-
`
|
|
22
|
-
(`
|
|
19
|
+
You opt in with `codegen subsystem install integration`, which vendors the runtime
|
|
20
|
+
into `<paths.subsystems>/integration/` (imported as `@shared/subsystems/integration`), adds a
|
|
21
|
+
`integration:` block to `codegen.config.yaml`, and emits the audit schema
|
|
22
|
+
(`integration-audit.schema.ts`). Unlike some subsystems, integration ships **no `generated/`
|
|
23
23
|
directory** — there are no codegen-emitted runtime artifacts from the base
|
|
24
24
|
install. (Per-entity change-source modules are emitted only if you declare a
|
|
25
25
|
`detection:` block in an entity YAML — see the change-sources L1 file.)
|
|
@@ -32,41 +32,41 @@ subsystem owns; step 1 is the only thing you write per provider:
|
|
|
32
32
|
1. **detect** upstream change *(you — `IChangeSource<T>`)*
|
|
33
33
|
2. **diff** against local state *(subsystem — `IFieldDiffer<T>`, default `DeepEqualDiffer`)*
|
|
34
34
|
3. **apply** the upsert or soft-delete *(your sink, called by the orchestrator)*
|
|
35
|
-
4. **record** the structured delta into `
|
|
35
|
+
4. **record** the structured delta into `integration_run_items` *(subsystem)*
|
|
36
36
|
5. **emit** an event on success *(you — wired in your sink, optional)*
|
|
37
37
|
|
|
38
38
|
Three detection modes (poll / CDC / webhook) converge on the single
|
|
39
39
|
`IChangeSource<T>` port; per-mode differences live in `Change<T>` metadata, not
|
|
40
40
|
in separate ports.
|
|
41
41
|
|
|
42
|
-
**
|
|
43
|
-
applies → records (`
|
|
42
|
+
**Integration is not events and not jobs.** Integration detects upstream change → diffs →
|
|
43
|
+
applies → records (`integration_runs` + `integration_run_items` pairs). It can be *triggered
|
|
44
44
|
by* a scheduled job (polling) or a webhook, and it can *emit* events on a
|
|
45
45
|
successful upsert — but the three subsystems have distinct lifecycles. See the
|
|
46
46
|
`jobs` and `events` skills for those.
|
|
47
47
|
|
|
48
|
-
**The audit is structured, not freeform.** `
|
|
48
|
+
**The audit is structured, not freeform.** `integration_run_items.changed_fields` is
|
|
49
49
|
`{ fieldName: { from, to } }` jsonb, validated at write time. That makes drift
|
|
50
50
|
queries ("when did this opportunity first become Closed Won?") one-shot SQL
|
|
51
51
|
filters instead of JSON scrapes.
|
|
52
52
|
|
|
53
53
|
## Wiring at a glance
|
|
54
54
|
|
|
55
|
-
`
|
|
55
|
+
`IntegrationModule.forRoot(...)` in `app.module.ts` wires the substrate — the cursor
|
|
56
56
|
store, run recorder, field differ, and multi-tenant flag. It is `global: true`
|
|
57
|
-
and **does NOT provide `
|
|
58
|
-
`
|
|
59
|
-
you register `
|
|
60
|
-
bindings. Putting it in `
|
|
57
|
+
and **does NOT provide `ExecuteIntegrationUseCase`**. The orchestrator depends on
|
|
58
|
+
`INTEGRATION_CHANGE_SOURCE` + `INTEGRATION_SINK`, which are per-entity and consumer-owned, so
|
|
59
|
+
you register `ExecuteIntegrationUseCase` in your *feature module* alongside those
|
|
60
|
+
bindings. Putting it in `IntegrationModule` would force Nest to resolve those tokens
|
|
61
61
|
at module compile time, before your feature module is imported.
|
|
62
62
|
|
|
63
63
|
```ts
|
|
64
|
-
import {
|
|
64
|
+
import { IntegrationModule } from '@shared/subsystems/integration';
|
|
65
65
|
|
|
66
66
|
@Module({
|
|
67
67
|
imports: [
|
|
68
68
|
DatabaseModule,
|
|
69
|
-
|
|
69
|
+
IntegrationModule.forRoot({ backend: 'drizzle' }), // 'memory' in tests
|
|
70
70
|
// ... per-entity feature modules, other subsystems
|
|
71
71
|
],
|
|
72
72
|
})
|
|
@@ -77,13 +77,13 @@ export class AppModule {}
|
|
|
77
77
|
|
|
78
78
|
| When the task involves… | Read |
|
|
79
79
|
|---|---|
|
|
80
|
-
| Implementing `IChangeSource<T>` or `
|
|
81
|
-
| The `
|
|
80
|
+
| Implementing `IChangeSource<T>` or `IIntegrationSink<T>`; the per-entity feature module; the `detection:` block + provider-keyed factory; triggering a run; multi-tenancy; loopback; testing | `change-sources-and-sinks.md` |
|
|
81
|
+
| The `integration_runs` / `integration_run_items` / `integration_subscriptions` shape; the structured `changed_fields` contract; worked drift / staleness / stuck-run queries; orchestrator run lifecycle and failure semantics | `audit-and-detection.md` |
|
|
82
82
|
|
|
83
83
|
## Non-obvious rules
|
|
84
84
|
|
|
85
85
|
1. **One port for three modes.** Poll, CDC, and webhook adapters all implement
|
|
86
|
-
`IChangeSource<T>` with `listChanges(subscription, cursor):
|
|
86
|
+
`IChangeSource<T>` with `listChanges(subscription, cursor): AintegrationIterable<Change<T>>`.
|
|
87
87
|
Per-mode concerns ride in `Change<T>` metadata (`source`, `dedupKey`,
|
|
88
88
|
`providerChangedFields`). Do not introduce `IPollSource` / `ICdcSource` /
|
|
89
89
|
`IWebhookSource` — the union is deliberate.
|
|
@@ -93,7 +93,7 @@ export class AppModule {}
|
|
|
93
93
|
The orchestrator is the only reader/writer of cursor storage — never inject
|
|
94
94
|
the cursor store inside a source or sink.
|
|
95
95
|
|
|
96
|
-
3. **`
|
|
96
|
+
3. **`IntegrationModule` does NOT provide `ExecuteIntegrationUseCase`.** Register the
|
|
97
97
|
orchestrator in your feature module's `providers` array next to your source
|
|
98
98
|
and sink bindings.
|
|
99
99
|
|
|
@@ -102,8 +102,8 @@ export class AppModule {}
|
|
|
102
102
|
insert (in both Drizzle and Memory backends). Do not treat it as freeform —
|
|
103
103
|
arbitrary keys break drift queries and get rejected.
|
|
104
104
|
|
|
105
|
-
5. **The
|
|
106
|
-
`
|
|
105
|
+
5. **The integration audit tables are subsystem-owned.** Query `integration_subscriptions`,
|
|
106
|
+
`integration_runs`, and `integration_run_items` freely for dashboards, but do not write to
|
|
107
107
|
them directly (bypassing the recorder's validation lands malformed data),
|
|
108
108
|
and do not author entity YAMLs for them (that produces redundant
|
|
109
109
|
repositories/services shadowing the subsystem).
|
|
@@ -124,9 +124,9 @@ export class AppModule {}
|
|
|
124
124
|
`IWebhookSource`). One `IChangeSource<T>` for all modes.
|
|
125
125
|
- Do not treat `changed_fields` as freeform jsonb — the `{ from, to }` shape is
|
|
126
126
|
load-bearing for drift queries and enforced at write.
|
|
127
|
-
- Do not provide `
|
|
127
|
+
- Do not provide `ExecuteIntegrationUseCase` in `IntegrationModule` — it forces eager
|
|
128
128
|
resolution of consumer-owned tokens.
|
|
129
|
-
- Do not write directly to the
|
|
129
|
+
- Do not write directly to the integration audit tables, and do not ship entity YAMLs
|
|
130
130
|
for them.
|
|
131
131
|
- Do not inject the cursor store inside a source or sink — the orchestrator
|
|
132
132
|
owns the get/put lifecycle.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Audit model, orchestrator flow, and diffing
|
|
4
4
|
|
|
5
|
-
The
|
|
5
|
+
The integration subsystem records every run into three tables and runs every
|
|
6
6
|
integration through one orchestrator loop. This file covers the table shapes,
|
|
7
7
|
the structured `changed_fields` contract, the queries you'll write against the
|
|
8
8
|
audit log, the orchestrator's run lifecycle and failure semantics, and how the
|
|
@@ -15,15 +15,15 @@ UIs, but never write to them directly (you'd bypass the recorder's validation),
|
|
|
15
15
|
and never author entity YAMLs for them (that produces redundant
|
|
16
16
|
repositories/services that shadow the subsystem).
|
|
17
17
|
|
|
18
|
-
### `
|
|
18
|
+
### `integration_subscriptions`
|
|
19
19
|
|
|
20
|
-
Cursor owner per `(
|
|
20
|
+
Cursor owner per `(connection_id, adapter, domain, external_ref)` tuple. The
|
|
21
21
|
cursor store reads/writes it.
|
|
22
22
|
|
|
23
23
|
| Column | Type | Notes |
|
|
24
24
|
|---|---|---|
|
|
25
25
|
| `id` | uuid PK | `defaultRandom()` |
|
|
26
|
-
| `
|
|
26
|
+
| `connection_id` | text | Opaque id of the connected account/instance (SFDC org id, GH installation id, …) |
|
|
27
27
|
| `adapter` | text | Short adapter label: `'salesforce'`, `'hubspot'` |
|
|
28
28
|
| `domain` | text | Canonical entity: `'opportunity'`, `'contact'` |
|
|
29
29
|
| `external_ref` | text NULL | Upstream scope (filter id, webhook subscription id); NULL = full domain |
|
|
@@ -31,21 +31,21 @@ cursor store reads/writes it.
|
|
|
31
31
|
| `config` | jsonb, default `{}` | Per-subscription config (`batchSize`, `highWatermark`, …) |
|
|
32
32
|
| `cursor` | jsonb NULL | Opaque; written by the cursor store; NULL until first successful run |
|
|
33
33
|
| `last_sync_at` | ts NULL | Stamped alongside `cursor` |
|
|
34
|
-
| `tenant_id` | text NULL | Present only when `
|
|
34
|
+
| `tenant_id` | text NULL | Present only when `integration.multi_tenant: true` |
|
|
35
35
|
| `created_at` / `updated_at` | ts | |
|
|
36
36
|
|
|
37
|
-
Indexes: a unique `(
|
|
37
|
+
Indexes: a unique `(connection_id, adapter, domain, external_ref)` tuple
|
|
38
38
|
(Postgres treats NULL `external_ref` as distinct — that's a consumer modeling
|
|
39
39
|
concern), and an `(enabled, last_sync_at)` scheduling index.
|
|
40
40
|
|
|
41
|
-
### `
|
|
41
|
+
### `integration_runs`
|
|
42
42
|
|
|
43
|
-
One row per `
|
|
43
|
+
One row per `ExecuteIntegrationUseCase.execute()` invocation.
|
|
44
44
|
|
|
45
45
|
| Column | Type | Notes |
|
|
46
46
|
|---|---|---|
|
|
47
47
|
| `id` | uuid PK | |
|
|
48
|
-
| `subscription_id` | uuid FK → `
|
|
48
|
+
| `subscription_id` | uuid FK → `integration_subscriptions.id` (cascade) | |
|
|
49
49
|
| `direction` | enum `inbound \| outbound` | Almost always `inbound`; `outbound` reserved for writeback |
|
|
50
50
|
| `action` | enum `poll \| cdc \| webhook \| manual \| writeback` | Provenance for self-identification |
|
|
51
51
|
| `status` | enum `running \| success \| no_changes \| failed` | `running` is in-flight only |
|
|
@@ -60,14 +60,14 @@ One row per `ExecuteSyncUseCase.execute()` invocation.
|
|
|
60
60
|
Indexes: `(subscription_id, started_at)` for timelines, `(status, started_at)`
|
|
61
61
|
for the stale-run sweeper.
|
|
62
62
|
|
|
63
|
-
### `
|
|
63
|
+
### `integration_run_items`
|
|
64
64
|
|
|
65
65
|
One row per upstream change processed within a run.
|
|
66
66
|
|
|
67
67
|
| Column | Type | Notes |
|
|
68
68
|
|---|---|---|
|
|
69
69
|
| `id` | uuid PK | |
|
|
70
|
-
| `
|
|
70
|
+
| `integration_run_id` | uuid FK → `integration_runs.id` (cascade) | |
|
|
71
71
|
| `entity_type` | text | Canonical domain (`'opportunity'`) |
|
|
72
72
|
| `external_id` | text | Upstream id |
|
|
73
73
|
| `local_id` | text NULL | Set on `created \| updated \| deleted`; null on `noop` |
|
|
@@ -79,7 +79,7 @@ One row per upstream change processed within a run.
|
|
|
79
79
|
| `created_at` | ts, default now | |
|
|
80
80
|
| `tenant_id` | text NULL | Present only when multi-tenant |
|
|
81
81
|
|
|
82
|
-
Indexes: `(
|
|
82
|
+
Indexes: `(integration_run_id, created_at)` for within-run timelines,
|
|
83
83
|
`(entity_type, external_id)` for per-record history.
|
|
84
84
|
|
|
85
85
|
## The `changed_fields` contract
|
|
@@ -119,12 +119,12 @@ taste, augment the differ's ignore list in your feature module (see Diffing).
|
|
|
119
119
|
|
|
120
120
|
## Common queries
|
|
121
121
|
|
|
122
|
-
**"What changed in the last 24 hours across all
|
|
122
|
+
**"What changed in the last 24 hours across all integration?"**
|
|
123
123
|
|
|
124
124
|
```sql
|
|
125
125
|
SELECT sr.action, sri.entity_type, sri.external_id, sri.operation, sri.changed_fields
|
|
126
|
-
FROM
|
|
127
|
-
JOIN
|
|
126
|
+
FROM integration_run_items sri
|
|
127
|
+
JOIN integration_runs sr ON sri.integration_run_id = sr.id
|
|
128
128
|
WHERE sri.created_at > now() - interval '1 day'
|
|
129
129
|
AND sri.status = 'success'
|
|
130
130
|
AND sri.operation != 'noop'
|
|
@@ -135,7 +135,7 @@ ORDER BY sri.created_at DESC;
|
|
|
135
135
|
|
|
136
136
|
```sql
|
|
137
137
|
SELECT id, adapter, domain, external_ref, last_sync_at
|
|
138
|
-
FROM
|
|
138
|
+
FROM integration_subscriptions
|
|
139
139
|
WHERE enabled = true
|
|
140
140
|
AND (last_sync_at IS NULL OR last_sync_at < now() - interval '1 hour')
|
|
141
141
|
ORDER BY last_sync_at ASC NULLS FIRST;
|
|
@@ -147,7 +147,7 @@ mid-run without reaching the completion path)
|
|
|
147
147
|
|
|
148
148
|
```sql
|
|
149
149
|
SELECT sr.id, sr.subscription_id, sr.started_at, sr.action
|
|
150
|
-
FROM
|
|
150
|
+
FROM integration_runs sr
|
|
151
151
|
WHERE sr.status = 'running'
|
|
152
152
|
AND sr.started_at < now() - interval '10 minutes';
|
|
153
153
|
```
|
|
@@ -156,7 +156,7 @@ WHERE sr.status = 'running'
|
|
|
156
156
|
|
|
157
157
|
```sql
|
|
158
158
|
SELECT sri.created_at
|
|
159
|
-
FROM
|
|
159
|
+
FROM integration_run_items sri
|
|
160
160
|
WHERE sri.entity_type = 'opportunity'
|
|
161
161
|
AND sri.external_id = '006Ab00000ABC'
|
|
162
162
|
AND sri.changed_fields -> 'stage_name' ->> 'to' = 'Closed Won'
|
|
@@ -173,7 +173,7 @@ SELECT sri.external_id,
|
|
|
173
173
|
sri.changed_fields -> 'amount' ->> 'from' AS old_amount,
|
|
174
174
|
sri.changed_fields -> 'amount' ->> 'to' AS new_amount,
|
|
175
175
|
sri.created_at
|
|
176
|
-
FROM
|
|
176
|
+
FROM integration_run_items sri
|
|
177
177
|
WHERE sri.entity_type = 'opportunity'
|
|
178
178
|
AND sri.created_at > now() - interval '7 days'
|
|
179
179
|
AND sri.changed_fields ? 'amount'
|
|
@@ -215,7 +215,7 @@ execute(input)
|
|
|
215
215
|
### Failure semantics worth memorizing
|
|
216
216
|
|
|
217
217
|
1. **`assertTenantId` fires before `startRun`.** Rejected multi-tenant inputs
|
|
218
|
-
never open a `
|
|
218
|
+
never open a `integration_runs` row — no dangling `status=running`. Backends
|
|
219
219
|
re-validate at their write boundary (defense in depth).
|
|
220
220
|
|
|
221
221
|
2. **Cursor advances per-yield, not per-success.** `latestCursor` updates on
|
|
@@ -289,7 +289,7 @@ as changes), but the diff output preserves the *raw* values:
|
|
|
289
289
|
cannot remove defaults):
|
|
290
290
|
|
|
291
291
|
```ts
|
|
292
|
-
{ provide:
|
|
292
|
+
{ provide: INTEGRATION_FIELD_DIFFER, useValue: new DeepEqualDiffer({ ignore: ['integration_version'] }) }
|
|
293
293
|
```
|
|
294
294
|
|
|
295
295
|
Bind it as `useValue: new DeepEqualDiffer(...)`, not `useClass` — the
|
|
@@ -299,4 +299,4 @@ constructor's optional options object confuses Nest's metadata reflection.
|
|
|
299
299
|
columns changed, set it on the `Change<T>` and the differ skips deep-equal over
|
|
300
300
|
untouched fields — but it still applies the ignore list. To write a fully
|
|
301
301
|
custom differ (type-aware enum normalization, hint-only inspection), implement
|
|
302
|
-
`IFieldDiffer<T>` and bind it to `
|
|
302
|
+
`IFieldDiffer<T>` and bind it to `INTEGRATION_FIELD_DIFFER`.
|