@pattern-stack/codegen 0.16.0 → 0.17.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.
Files changed (112) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/consumer-skills/entities/families-and-queries.md +5 -3
  3. package/consumer-skills/integration/change-sources-and-sinks.md +1 -1
  4. package/dist/{chunk-3RWMQC3K.js → chunk-3MAZ4TQH.js} +12 -12
  5. package/dist/{chunk-VNBC3VXM.js → chunk-3VEVGL74.js} +4 -4
  6. package/dist/{chunk-WWGYCIJX.js → chunk-43SBT72G.js} +2 -2
  7. package/dist/{chunk-Y7GDG744.js → chunk-4GLNY5V6.js} +5 -5
  8. package/dist/{chunk-BK5ICA2F.js → chunk-4MVGAMUA.js} +4 -4
  9. package/dist/{chunk-3NMCDN7L.js → chunk-5TK7MEN4.js} +2 -2
  10. package/dist/chunk-5TK7MEN4.js.map +1 -0
  11. package/dist/{chunk-T6SCOJF4.js → chunk-7LKAMLV4.js} +4 -4
  12. package/dist/{chunk-BHZP6LOV.js → chunk-CDLWYZVQ.js} +7 -7
  13. package/dist/{chunk-DKKFTHHI.js → chunk-CZQUOIDY.js} +4 -4
  14. package/dist/{chunk-XWBK3XJK.js → chunk-DCCZB4UC.js} +4 -4
  15. package/dist/{chunk-EBKVKN75.js → chunk-DTXH24LR.js} +2 -2
  16. package/dist/{chunk-RUYLXR5F.js → chunk-GJDEPTPY.js} +10 -10
  17. package/dist/{chunk-32DOFN3T.js → chunk-IOQMMH6C.js} +17 -7
  18. package/dist/{chunk-32DOFN3T.js.map → chunk-IOQMMH6C.js.map} +1 -1
  19. package/dist/{chunk-BOPZWRJK.js → chunk-JYBFPNBJ.js} +8 -8
  20. package/dist/chunk-JYBFPNBJ.js.map +1 -0
  21. package/dist/{chunk-KSTZIULO.js → chunk-K2I6XIK5.js} +4 -4
  22. package/dist/{chunk-CEWLVVAH.js → chunk-L3VJ47BU.js} +5 -5
  23. package/dist/chunk-MKWQKKK7.js +72 -0
  24. package/dist/chunk-MKWQKKK7.js.map +1 -0
  25. package/dist/{chunk-DRCLNYH7.js → chunk-NXNVTXKG.js} +4 -4
  26. package/dist/{chunk-TDEHU73T.js → chunk-OGIZXGPY.js} +4 -4
  27. package/dist/{chunk-XDIIVIIK.js → chunk-OITTYGJS.js} +4 -4
  28. package/dist/{chunk-24WXSC3C.js → chunk-P3AYBRP6.js} +7 -7
  29. package/dist/{chunk-EJBK7I4F.js → chunk-RHYNACZS.js} +3 -3
  30. package/dist/{chunk-YK5JEVLX.js → chunk-SR7F3TJY.js} +4 -4
  31. package/dist/{chunk-YLPAPPLW.js → chunk-TIZXQU26.js} +36 -9
  32. package/dist/chunk-TIZXQU26.js.map +1 -0
  33. package/dist/{chunk-4PFF3ED4.js → chunk-UTNWFHJF.js} +4 -4
  34. package/dist/{chunk-LQ6PYFU6.js → chunk-Z7PQCAVK.js} +4 -4
  35. package/dist/runtime/base-classes/activity-entity-repository.d.ts +39 -7
  36. package/dist/runtime/base-classes/activity-entity-repository.js +1 -1
  37. package/dist/runtime/base-classes/activity-entity-service.d.ts +12 -10
  38. package/dist/runtime/base-classes/activity-entity-service.js +1 -1
  39. package/dist/runtime/base-classes/index.js +23 -23
  40. package/dist/runtime/shared/openapi/index.js +7 -7
  41. package/dist/runtime/shared/openapi/registry.js +2 -2
  42. package/dist/runtime/subsystems/analytics/analytics.module.js +2 -2
  43. package/dist/runtime/subsystems/analytics/index.js +4 -4
  44. package/dist/runtime/subsystems/auth/auth.module.js +3 -3
  45. package/dist/runtime/subsystems/auth/index.js +7 -7
  46. package/dist/runtime/subsystems/bridge/bridge-delivery-handler.js +2 -2
  47. package/dist/runtime/subsystems/bridge/bridge-delivery.drizzle-backend.js +2 -2
  48. package/dist/runtime/subsystems/bridge/bridge-outbox-drain-hook.js +4 -4
  49. package/dist/runtime/subsystems/bridge/bridge.module.js +15 -15
  50. package/dist/runtime/subsystems/bridge/index.js +17 -17
  51. package/dist/runtime/subsystems/cache/cache.module.js +1 -1
  52. package/dist/runtime/subsystems/cache/index.js +3 -3
  53. package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js +2 -2
  54. package/dist/runtime/subsystems/events/event-bus.memory-backend.js +2 -2
  55. package/dist/runtime/subsystems/events/events.module.js +4 -4
  56. package/dist/runtime/subsystems/events/index.js +4 -4
  57. package/dist/runtime/subsystems/index.js +107 -107
  58. package/dist/runtime/subsystems/integration/build-change-source.js +2 -2
  59. package/dist/runtime/subsystems/integration/detection-config.schema.d.ts +23 -15
  60. package/dist/runtime/subsystems/integration/detection-config.schema.js +1 -1
  61. package/dist/runtime/subsystems/integration/execute-integration.use-case.js +2 -2
  62. package/dist/runtime/subsystems/integration/index.js +43 -43
  63. package/dist/runtime/subsystems/integration/integration-cursor-store.drizzle-backend.js +2 -2
  64. package/dist/runtime/subsystems/integration/integration-run-recorder.drizzle-backend.js +2 -2
  65. package/dist/runtime/subsystems/integration/integration.module.js +5 -5
  66. package/dist/runtime/subsystems/integration/webhook-change-source.d.ts +36 -6
  67. package/dist/runtime/subsystems/integration/webhook-change-source.js +1 -1
  68. package/dist/runtime/subsystems/jobs/index.js +30 -30
  69. package/dist/runtime/subsystems/jobs/job-orchestrator.bullmq-backend.js +4 -4
  70. package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.js +1 -1
  71. package/dist/runtime/subsystems/jobs/job-run-service.drizzle-backend.js +2 -2
  72. package/dist/runtime/subsystems/jobs/job-run-service.memory-backend.js +2 -2
  73. package/dist/runtime/subsystems/jobs/job-worker.js +2 -2
  74. package/dist/runtime/subsystems/jobs/job-worker.module.js +10 -10
  75. package/dist/runtime/subsystems/jobs/jobs-domain.module.js +8 -8
  76. package/dist/runtime/subsystems/storage/index.js +4 -4
  77. package/dist/runtime/subsystems/storage/storage.module.js +2 -2
  78. package/dist/src/cli/index.js +15 -15
  79. package/dist/src/index.d.ts +34 -19
  80. package/dist/src/index.js +14 -14
  81. package/package.json +2 -1
  82. package/runtime/base-classes/activity-entity-repository.ts +72 -13
  83. package/runtime/base-classes/activity-entity-service.ts +14 -12
  84. package/runtime/subsystems/integration/detection-config.schema.ts +64 -54
  85. package/runtime/subsystems/integration/webhook-change-source.ts +187 -133
  86. package/src/patterns/library/activity.pattern.ts +40 -10
  87. package/dist/chunk-3NMCDN7L.js.map +0 -1
  88. package/dist/chunk-BOPZWRJK.js.map +0 -1
  89. package/dist/chunk-XCEI7NUH.js +0 -41
  90. package/dist/chunk-XCEI7NUH.js.map +0 -1
  91. package/dist/chunk-YLPAPPLW.js.map +0 -1
  92. /package/dist/{chunk-3RWMQC3K.js.map → chunk-3MAZ4TQH.js.map} +0 -0
  93. /package/dist/{chunk-VNBC3VXM.js.map → chunk-3VEVGL74.js.map} +0 -0
  94. /package/dist/{chunk-WWGYCIJX.js.map → chunk-43SBT72G.js.map} +0 -0
  95. /package/dist/{chunk-Y7GDG744.js.map → chunk-4GLNY5V6.js.map} +0 -0
  96. /package/dist/{chunk-BK5ICA2F.js.map → chunk-4MVGAMUA.js.map} +0 -0
  97. /package/dist/{chunk-T6SCOJF4.js.map → chunk-7LKAMLV4.js.map} +0 -0
  98. /package/dist/{chunk-BHZP6LOV.js.map → chunk-CDLWYZVQ.js.map} +0 -0
  99. /package/dist/{chunk-DKKFTHHI.js.map → chunk-CZQUOIDY.js.map} +0 -0
  100. /package/dist/{chunk-XWBK3XJK.js.map → chunk-DCCZB4UC.js.map} +0 -0
  101. /package/dist/{chunk-EBKVKN75.js.map → chunk-DTXH24LR.js.map} +0 -0
  102. /package/dist/{chunk-RUYLXR5F.js.map → chunk-GJDEPTPY.js.map} +0 -0
  103. /package/dist/{chunk-KSTZIULO.js.map → chunk-K2I6XIK5.js.map} +0 -0
  104. /package/dist/{chunk-CEWLVVAH.js.map → chunk-L3VJ47BU.js.map} +0 -0
  105. /package/dist/{chunk-DRCLNYH7.js.map → chunk-NXNVTXKG.js.map} +0 -0
  106. /package/dist/{chunk-TDEHU73T.js.map → chunk-OGIZXGPY.js.map} +0 -0
  107. /package/dist/{chunk-XDIIVIIK.js.map → chunk-OITTYGJS.js.map} +0 -0
  108. /package/dist/{chunk-24WXSC3C.js.map → chunk-P3AYBRP6.js.map} +0 -0
  109. /package/dist/{chunk-EJBK7I4F.js.map → chunk-RHYNACZS.js.map} +0 -0
  110. /package/dist/{chunk-YK5JEVLX.js.map → chunk-SR7F3TJY.js.map} +0 -0
  111. /package/dist/{chunk-4PFF3ED4.js.map → chunk-UTNWFHJF.js.map} +0 -0
  112. /package/dist/{chunk-LQ6PYFU6.js.map → chunk-Z7PQCAVK.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,99 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.17.0] — 2026-06-04
8
+
9
+ **`ActivityPattern` subject scoping is config-driven** (ACTIVITY-SUBJECT-1) —
10
+ the library's Activity base classes no longer bake the CRM term "opportunity"
11
+ into their finders. An activity/interaction entity declares which subject it is
12
+ scoped to via the pattern's new `config:` block, and the generated repo/service
13
+ expose generic, config-resolved subject lookups. Surfaced by the swe-brain
14
+ dogfood, whose interactions (meeting, email, transcript, message) reference
15
+ `person`/`repo`/`team` subjects (ADR-0006), not CRM opportunities.
16
+
17
+ Consumer census confirmed **no project used the Activity pattern** (dealbrain's
18
+ sole `findByOpportunityId` is a `JunctionSyncRepository` method, not the pattern;
19
+ swe-brain's interactions are all `pattern: Integrated`), so this is a clean cut
20
+ with no aliases per the "no backwards compatibility until users" rule. The
21
+ `patterns: [Integrated, Activity]` composition — the swe-brain target — is
22
+ validated and tested.
23
+
24
+ ### Added
25
+
26
+ - **`ActivityPattern.configSchema`** — `{ subject?, subjectColumn?, occurredAt? }`
27
+ (all optional, `.strict()`). `subject` derives the FK column `<subject>_id`;
28
+ `subjectColumn` overrides it explicitly; `occurredAt` names the recency column
29
+ (default `occurred_at`). Validated at parse time via the standard ADR-031
30
+ composition path; emitted onto the concrete repo as `patternConfig` (the same
31
+ hand-off `IntegratedEntityRepository` uses for `integrationConfig`).
32
+ - **`ActivityPatternConfig`** interface exported from
33
+ `runtime/base-classes/activity-entity-repository.ts`.
34
+
35
+ ### Changed
36
+
37
+ - **`ActivityEntityRepository` finders are config-driven.**
38
+ `findByOpportunityId` / `findRecentByOpportunityId` are replaced by
39
+ `findBySubjectId` / `findRecentBySubjectId`, which resolve the subject FK column
40
+ (and recency-ordering column) from `this.patternConfig` at runtime. Calling a
41
+ subject finder with no subject configured throws a clear error naming the
42
+ config key to set. `findByDateRange` and `findByUserId` are unchanged (actor
43
+ scoping is generally applicable, not CRM-shaped).
44
+ - **`ActivityEntityService`** mirrors the rename: `findBySubject` /
45
+ `findRecent` (was `findByOpportunity` / `findRecent`); `IActivityEntityRepository`
46
+ drops the opportunity methods for the subject ones. `findByDateRange` /
47
+ `findByUser` unchanged.
48
+ - **`ActivityPattern` inherited-method comment strings** now advertise the
49
+ subject finders; the header's byte-identical-to-FAMILY_MAP claim is removed (it
50
+ was a one-time PATTERN-5 migration guarantee, not a standing contract).
51
+
52
+ ### Migration
53
+
54
+ No consumer action required — no project used the Activity pattern. A project
55
+ adopting it now declares `pattern: Activity` (or `patterns: [Integrated,
56
+ Activity]`) plus `config: { Activity: { subject: <entity> } }`. Named per-subject
57
+ finders (`findByPersonId`) remain available the same way they always were — via
58
+ the entity's declarative `queries:` block.
59
+
60
+ ## [0.16.1] — 2026-06-04
61
+
62
+ **`WebhookFetchCallback<T>` yields `{ record, eventId?, cursor? }`** —
63
+ `WebhookChangeSource` now prefers a queue-yielded `eventId` for
64
+ `Change<T>.dedupKey` (gap #6 follow-through, swe-brain ADR-0009 Amendment B
65
+ §B5). swe-brain's Slack inbound drain documented an `eventIdField: 'externalId'`
66
+ substitution — delivery dedup happens at the receiver, so record identity stood
67
+ in for event identity. That substitution becomes genuinely unsafe once a message
68
+ and its edit (same `externalId`, different vendor event) can share one drain
69
+ batch — they'd collapse to a single `dedupKey`. Vendor delivery metadata (the
70
+ event id) should never need a field on the vendor-neutral canonical record; the
71
+ queue-yield is the right channel for it. Backward-compatible: callbacks that
72
+ yield `{ record, cursor? }` and configs that set `webhook.eventIdField` are
73
+ unchanged; opting into `eventId` is the only migration, and it's optional.
74
+
75
+ ### Changed
76
+
77
+ - **`WebhookFetchCallback<T>` yield shape** is now `{ record: T; eventId?:
78
+ string; cursor?: WebhookCursor }` (was `{ record: T; cursor?: WebhookCursor }`)
79
+ — the new `eventId` is opt-in and additive; existing callbacks compile and run
80
+ unchanged.
81
+ - **`WebhookChangeSource.dedupKey` precedence** is now **yielded `eventId` >
82
+ `webhook.eventIdField` record extraction > undefined**. A non-empty yielded
83
+ `eventId` always wins; otherwise the configured `eventIdField` is read off the
84
+ emitted record (and still throws if the field is configured but absent on the
85
+ record); with neither, `dedupKey` is `undefined` (the orchestrator simply has
86
+ no delivery-level dedup signal for that change).
87
+ - **`detection-config.schema.ts`: `webhook.eventIdField` is now optional**
88
+ (`z.string().min(1).optional()`). A callback that always yields `eventId` need
89
+ not declare a record field for it. The `webhook` block itself stays
90
+ structurally required in webhook mode (an empty `{}` is valid; a missing block
91
+ is not), so the existing "webhook-mode missing webhook block" validation is
92
+ unaffected.
93
+
94
+ ### Docs
95
+
96
+ - ADR-033 §1 amended (the `webhook: { eventIdField? }` shape + the yield channel
97
+ + dedupKey precedence), integration `SKILL.md` + consumer
98
+ `change-sources-and-sinks.md` updated to the yield-preferred precedence.
99
+
7
100
  ## [0.16.0] — 2026-06-04
8
101
 
9
102
  **Postgres LISTEN/NOTIFY wakeups** for the jobs worker + events outbox drainer
@@ -16,7 +16,7 @@ an optional `tx?: DrizzleTx` for transactional composition.
16
16
  |---|---|---|
17
17
  | `Base` | plain tables with no special access pattern | nothing — standard CRUD only |
18
18
  | `Synced` | records mirrored from an external system (have an external id + per-user visibility) | `findByExternalId`, `findAllByUserId`, `findVisibleByUserId`, `syncUpsert` |
19
- | `Activity` | time-ordered activity/event rows tied to a parent | `findByDateRange`, `findByUserId`, `findByOpportunityId`, `findRecentByOpportunityId` |
19
+ | `Activity` | time-ordered activity/interaction rows scoped to a subject | `findByDateRange`, `findByUserId`, `findBySubjectId`, `findRecentBySubjectId` (subject FK + recency column resolved from `config: { Activity: { subject: <entity> } }`) |
20
20
  | `Metadata` | key/value or definition/value rows describing other entities | `findByEntityIdAndType`, `listByEntityId`, `listHistoryByEntityId` |
21
21
  | `Knowledge` | semantically-searchable knowledge rows (pgvector at runtime) | `semanticSearch`, `findPendingByOpportunityId`, `updateStatus`, `updateStatusBatch` |
22
22
 
@@ -77,6 +77,8 @@ and a `GET /<plural>/search` route. `paginate: true` makes the route accept
77
77
  - **`order:` is the default sort**, not a parameter — add a `queries:` search
78
78
  entry if you need caller-controlled ordering.
79
79
  - **Family methods assume their columns exist.** `Synced` expects an external-id
80
- + user-visibility shape; `Activity` expects a parent FK like
81
- `opportunity_id`. If your table doesn't fit, pick `Base` and add explicit
80
+ + user-visibility shape; `Activity`'s subject finders expect the subject FK
81
+ named by its `config:` (`subject: person` `person_id`, or an explicit
82
+ `subjectColumn`) plus a recency column (`occurred_at` by default, or
83
+ `config.occurredAt`). If your table doesn't fit, pick `Base` and add explicit
82
84
  `queries:`.
@@ -75,7 +75,7 @@ interface Change<T> {
75
75
  record: T; // canonical shape — provider mapping happens in the adapter
76
76
  cursor: unknown; // typed internally; opaque at the seam
77
77
  source: 'poll' | 'cdc' | 'webhook'; // provenance for the run-log audit
78
- dedupKey?: string; // CDC replay_id / webhook event_id when available
78
+ dedupKey?: string; // CDC replay_id / webhook event id when available (webhook: prefers the eventId yielded by WebhookFetchCallback, else webhook.eventIdField)
79
79
  providerChangedFields?: string[]; // CDC-only hint; lets the differ skip untouched fields
80
80
  }
81
81
  ```
@@ -1,21 +1,18 @@
1
- import {
2
- DrizzleJobStepService
3
- } from "./chunk-DV4RV2DC.js";
4
- import {
5
- DrizzleJobOrchestrator
6
- } from "./chunk-OTR44OH6.js";
7
1
  import {
8
2
  MemoryJobOrchestrator
9
3
  } from "./chunk-BULPAAD3.js";
10
- import {
11
- MemoryJobStepService
12
- } from "./chunk-PNZSGAB2.js";
13
4
  import {
14
5
  DrizzleJobRunService
15
- } from "./chunk-VNBC3VXM.js";
6
+ } from "./chunk-3VEVGL74.js";
16
7
  import {
17
8
  MemoryJobRunService
18
- } from "./chunk-BHZP6LOV.js";
9
+ } from "./chunk-CDLWYZVQ.js";
10
+ import {
11
+ DrizzleJobStepService
12
+ } from "./chunk-DV4RV2DC.js";
13
+ import {
14
+ MemoryJobStepService
15
+ } from "./chunk-PNZSGAB2.js";
19
16
  import {
20
17
  MemoryJobStore
21
18
  } from "./chunk-SNQ3TOWP.js";
@@ -24,6 +21,9 @@ import {
24
21
  BULLMQ_RESOLVED_CONFIG,
25
22
  resolveBullMqConfig
26
23
  } from "./chunk-I6MVCB5A.js";
24
+ import {
25
+ DrizzleJobOrchestrator
26
+ } from "./chunk-OTR44OH6.js";
27
27
  import {
28
28
  JOBS_LISTEN_NOTIFY,
29
29
  JOBS_MULTI_TENANT,
@@ -114,4 +114,4 @@ JobsDomainModule = __decorateClass([
114
114
  export {
115
115
  JobsDomainModule
116
116
  };
117
- //# sourceMappingURL=chunk-3RWMQC3K.js.map
117
+ //# sourceMappingURL=chunk-3MAZ4TQH.js.map
@@ -1,12 +1,12 @@
1
- import {
2
- MissingTenantIdError
3
- } from "./chunk-T4BIIU5E.js";
4
1
  import {
5
2
  clampLimit,
6
3
  decodeKeysetCursor,
7
4
  encodeKeysetCursor,
8
5
  toJobRunSummary
9
6
  } from "./chunk-L3LZWWSX.js";
7
+ import {
8
+ MissingTenantIdError
9
+ } from "./chunk-T4BIIU5E.js";
10
10
  import {
11
11
  JOBS_MULTI_TENANT,
12
12
  JOB_ORCHESTRATOR
@@ -198,4 +198,4 @@ DrizzleJobRunService = __decorateClass([
198
198
  export {
199
199
  DrizzleJobRunService
200
200
  };
201
- //# sourceMappingURL=chunk-VNBC3VXM.js.map
201
+ //# sourceMappingURL=chunk-3VEVGL74.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-4MF3HKJA.js";
4
4
  import {
5
5
  WebhookChangeSource
6
- } from "./chunk-YLPAPPLW.js";
6
+ } from "./chunk-TIZXQU26.js";
7
7
 
8
8
  // runtime/subsystems/integration/build-change-source.ts
9
9
  function buildChangeSource(cfg, fetch, middlewares = []) {
@@ -26,4 +26,4 @@ function buildChangeSource(cfg, fetch, middlewares = []) {
26
26
  export {
27
27
  buildChangeSource
28
28
  };
29
- //# sourceMappingURL=chunk-WWGYCIJX.js.map
29
+ //# sourceMappingURL=chunk-43SBT72G.js.map
@@ -1,11 +1,11 @@
1
- import {
2
- ERROR_RESPONSE_SCHEMA_NAME,
3
- errorResponseSchema
4
- } from "./chunk-SOVM2VEK.js";
5
1
  import {
6
2
  DuplicateSchemaError,
7
3
  OpenApiPeerDepMissingError
8
4
  } from "./chunk-YSLTTQLC.js";
5
+ import {
6
+ ERROR_RESPONSE_SCHEMA_NAME,
7
+ errorResponseSchema
8
+ } from "./chunk-SOVM2VEK.js";
9
9
 
10
10
  // runtime/shared/openapi/registry.ts
11
11
  var OpenApiRegistry = class {
@@ -85,4 +85,4 @@ var OpenApiRegistry = class {
85
85
  export {
86
86
  OpenApiRegistry
87
87
  };
88
- //# sourceMappingURL=chunk-Y7GDG744.js.map
88
+ //# sourceMappingURL=chunk-4GLNY5V6.js.map
@@ -1,12 +1,12 @@
1
- import {
2
- STORAGE
3
- } from "./chunk-NYBCQZC7.js";
4
1
  import {
5
2
  LocalStorageBackend
6
3
  } from "./chunk-JWNHNUYL.js";
7
4
  import {
8
5
  MemoryStorageBackend
9
6
  } from "./chunk-3SZFUTXE.js";
7
+ import {
8
+ STORAGE
9
+ } from "./chunk-NYBCQZC7.js";
10
10
  import {
11
11
  __decorateClass
12
12
  } from "./chunk-2E224ZSN.js";
@@ -37,4 +37,4 @@ StorageModule = __decorateClass([
37
37
  export {
38
38
  StorageModule
39
39
  };
40
- //# sourceMappingURL=chunk-BK5ICA2F.js.map
40
+ //# sourceMappingURL=chunk-4MVGAMUA.js.map
@@ -58,7 +58,7 @@ var PollDetectionSchema = z.object({
58
58
  provenance: z.enum(["poll", "cdc"]).optional()
59
59
  });
60
60
  var WebhookDetectionSchema = z.object({
61
- eventIdField: z.string().min(1)
61
+ eventIdField: z.string().min(1).optional()
62
62
  });
63
63
  var PollModeSchema = z.object({
64
64
  mode: z.literal("poll"),
@@ -87,4 +87,4 @@ export {
87
87
  WebhookDetectionSchema,
88
88
  DetectionConfigSchema
89
89
  };
90
- //# sourceMappingURL=chunk-3NMCDN7L.js.map
90
+ //# sourceMappingURL=chunk-5TK7MEN4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../runtime/subsystems/integration/detection-config.schema.ts"],"sourcesContent":["/**\n * Integration subsystem — DetectionConfig schema (#226-1)\n *\n * Canonical Zod schema for per-entity integration detection config. The schema is\n * the single source of truth for filter/mapping shape and is consumed by:\n *\n * 1. Runtime primitives — `PollChangeSource<T>`, `WebhookChangeSource<T>`\n * (#226-3, #226-4) accept a parsed `DetectionConfig` at construction.\n * 2. Codegen — `src/schema/entity-definition.schema.ts` (#226-6) imports\n * this schema so per-entity YAML `detection:` blocks validate against\n * the same shape the runtime enforces.\n *\n * Locked decisions (see ADR-033 + decision memo Q1–Q6):\n * - Filter vocabulary is flat AND of `{ field, op, value }` triples; richer\n * boolean expressions (OR / NOT / nested) are deferred per epic open Q3.\n * - Cursor strategy is a tagged union over the four shapes the three modes\n * need (`systemModstamp`, `replayId`, `timestamp`, `eventId`). Each\n * strategy types its cursor internally; the orchestrator persists what\n * the iterator last yielded (integration skill rule 2).\n * - `mode: 'poll'` may opt into `provenance: 'cdc'` so Stripe-style event\n * endpoints (mechanically a poll, semantically CDC) reuse the poll\n * primitive while emitting `Change<T>.source = 'cdc'`. Long-lived\n * streaming CDC (SFDC Pub-Sub, Debezium) is a separate primitive\n * deferred to #226-8.\n * - `webhook` mode's `eventIdField` is optional: `WebhookChangeSource<T>`\n * prefers an `eventId` yielded by the queue iterator and falls back to the\n * `eventIdField` record extraction (precedence: yielded eventId >\n * eventIdField extraction > undefined dedupKey).\n */\nimport { z } from \"zod\";\n\n// ============================================================================\n// Field mapping — provider field → canonical target\n// ============================================================================\n\n/**\n * Maps a single provider field onto the canonical record. `transform` is an\n * opt-in tag the adapter callback may inspect (`date-iso`, `decimal-string`,\n * etc.); the schema does not enumerate transforms — adapters interpret them.\n */\nexport const FieldMappingSchema = z.object({\n\tsource: z.string().min(1),\n\ttarget: z.string().min(1),\n\ttransform: z.string().min(1).optional(),\n});\n\nexport type FieldMapping = z.infer<typeof FieldMappingSchema>;\n\n// ============================================================================\n// Resolved filter — flat-AND triple\n// ============================================================================\n\n/**\n * A single resolved filter clause applied at fetch time. `value` is `unknown`\n * to admit primitives, arrays (for `in` / `nin`), and dates as ISO strings —\n * adapters interpret per provider.\n */\nexport const ResolvedFilterSchema = z.object({\n\tfield: z.string().min(1),\n\top: z.enum([\"eq\", \"neq\", \"in\", \"nin\", \"gt\", \"gte\", \"lt\", \"lte\"]),\n\tvalue: z.unknown(),\n});\n\nexport type ResolvedFilter = z.infer<typeof ResolvedFilterSchema>;\n\n// ============================================================================\n// Cursor strategy — tagged union over the four shapes the modes need\n// ============================================================================\n\nconst SystemModstampCursorSchema = z.object({\n\tkind: z.literal(\"systemModstamp\"),\n\tfield: z.string().min(1),\n});\n\nconst ReplayIdCursorSchema = z.object({\n\tkind: z.literal(\"replayId\"),\n\tfield: z.string().min(1),\n});\n\nconst TimestampCursorSchema = z.object({\n\tkind: z.literal(\"timestamp\"),\n\tfield: z.string().min(1),\n});\n\nconst EventIdCursorSchema = z.object({\n\tkind: z.literal(\"eventId\"),\n\tfield: z.string().min(1),\n});\n\n/**\n * Gmail `historyId` (RFC-0003 §3) — an opaque, atomic vendor token. The next\n * watermark only exists at end-of-walk; there is no resumable mid-walk value.\n * `field` is metadata for codegen/adapters (the response key the token lives on).\n */\nconst HistoryIdCursorSchema = z.object({\n\tkind: z.literal(\"historyId\"),\n\tfield: z.string().min(1),\n});\n\n/**\n * Google Calendar `syncToken` (RFC-0003 §3) — an opaque, atomic sync token,\n * same divisibility profile as `historyId`.\n */\nconst SyncTokenCursorSchema = z.object({\n\tkind: z.literal(\"syncToken\"),\n\tfield: z.string().min(1),\n});\n\nexport const CursorStrategySchema = z.discriminatedUnion(\"kind\", [\n\tSystemModstampCursorSchema,\n\tReplayIdCursorSchema,\n\tTimestampCursorSchema,\n\tEventIdCursorSchema,\n\tHistoryIdCursorSchema,\n\tSyncTokenCursorSchema,\n]);\n\nexport type CursorStrategy = z.infer<typeof CursorStrategySchema>;\n\n// ============================================================================\n// Cursor divisibility (RFC-0003 §3)\n// ============================================================================\n\n/**\n * Whether a cursor strategy is *divisible* — a property of the strategy, not\n * the read primitive. Divisible cursors are sortable/monotonic watermarks whose\n * value is meaningful AS OF any single record (HubSpot `systemModstamp`, a\n * `timestamp` field, a Salesforce CDC `replayId`); the read primitive may\n * checkpoint per-ref mid-walk, so a crash resumes from the last delivered ref.\n *\n * Atomic cursors are opaque vendor tokens (Gmail `historyId`, Calendar\n * `syncToken`, a generic `eventId`) whose next value only exists at end-of-walk.\n * The primitive must withhold per-ref cursors and emit the token only at a safe\n * boundary, so an interrupted run never persists an unresumable mid-walk token\n * (it resumes all-or-nothing from the prior token — see `IncrementalReadBase`).\n *\n * `eventId` is classified atomic conservatively: a generic opaque id is treated\n * all-or-nothing unless a concrete strategy proves it monotonically resumable.\n */\nexport const CURSOR_DIVISIBILITY: Readonly<\n\tRecord<CursorStrategy[\"kind\"], boolean>\n> = {\n\tsystemModstamp: true,\n\ttimestamp: true,\n\treplayId: true,\n\teventId: false,\n\thistoryId: false,\n\tsyncToken: false,\n};\n\n/** Predicate form of {@link CURSOR_DIVISIBILITY}. */\nexport function isDivisibleCursor(kind: CursorStrategy[\"kind\"]): boolean {\n\treturn CURSOR_DIVISIBILITY[kind];\n}\n\n// ============================================================================\n// Mode-specific blocks\n// ============================================================================\n\n/**\n * Poll-mode block. `provenance: 'cdc'` opts the poll primitive into stamping\n * `Change<T>.source = 'cdc'` and populating `dedupKey` from the cursor's\n * `field` — used for Stripe-style event endpoints. Defaults to `'poll'`.\n */\nexport const PollDetectionSchema = z.object({\n\tcursor: CursorStrategySchema,\n\tprovenance: z.enum([\"poll\", \"cdc\"]).optional(),\n});\n\nexport type PollDetection = z.infer<typeof PollDetectionSchema>;\n\n/**\n * Webhook-mode block. `eventIdField`, when present, names the field on the\n * emitted canonical record that `WebhookChangeSource<T>` reads to set\n * `Change<T>.dedupKey` — used only as the fallback when the queue iterator\n * does NOT yield an `eventId` alongside the record.\n *\n * `eventIdField` is **optional**: a queue iterator that always yields an\n * `eventId` (vendor delivery metadata, the preferred channel) need not declare\n * a record field for it. dedupKey precedence is: yielded `eventId` >\n * `eventIdField` record extraction > undefined.\n */\nexport const WebhookDetectionSchema = z.object({\n\teventIdField: z.string().min(1).optional(),\n});\n\nexport type WebhookDetection = z.infer<typeof WebhookDetectionSchema>;\n\n// ============================================================================\n// DetectionConfig — top-level discriminated union over `mode`\n// ============================================================================\n\nconst PollModeSchema = z.object({\n\tmode: z.literal(\"poll\"),\n\tpoll: PollDetectionSchema,\n\tmapping: z.array(FieldMappingSchema).min(1),\n\tfilters: z.array(ResolvedFilterSchema).default([]),\n});\n\nconst WebhookModeSchema = z.object({\n\tmode: z.literal(\"webhook\"),\n\twebhook: WebhookDetectionSchema,\n\tmapping: z.array(FieldMappingSchema).min(1),\n\tfilters: z.array(ResolvedFilterSchema).default([]),\n});\n\n/**\n * Top-level detection config. Discriminated on `mode` so the relevant\n * mode-block (poll/webhook) is structurally required for that mode. CDC as a\n * long-lived streaming primitive is deferred (#226-8); CDC-as-provenance\n * (Stripe-style event endpoints) is expressed via `mode: 'poll'` with\n * `poll.provenance: 'cdc'`.\n */\nexport const DetectionConfigSchema = z.discriminatedUnion(\"mode\", [\n\tPollModeSchema,\n\tWebhookModeSchema,\n]);\n\nexport type DetectionConfig = z.infer<typeof DetectionConfigSchema>;\n"],"mappings":";AA6BA,SAAS,SAAS;AAWX,IAAM,qBAAqB,EAAE,OAAO;AAAA,EAC1C,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACxB,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACxB,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AACvC,CAAC;AAaM,IAAM,uBAAuB,EAAE,OAAO;AAAA,EAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACvB,IAAI,EAAE,KAAK,CAAC,MAAM,OAAO,MAAM,OAAO,MAAM,OAAO,MAAM,KAAK,CAAC;AAAA,EAC/D,OAAO,EAAE,QAAQ;AAClB,CAAC;AAQD,IAAM,6BAA6B,EAAE,OAAO;AAAA,EAC3C,MAAM,EAAE,QAAQ,gBAAgB;AAAA,EAChC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;AACxB,CAAC;AAED,IAAM,uBAAuB,EAAE,OAAO;AAAA,EACrC,MAAM,EAAE,QAAQ,UAAU;AAAA,EAC1B,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;AACxB,CAAC;AAED,IAAM,wBAAwB,EAAE,OAAO;AAAA,EACtC,MAAM,EAAE,QAAQ,WAAW;AAAA,EAC3B,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;AACxB,CAAC;AAED,IAAM,sBAAsB,EAAE,OAAO;AAAA,EACpC,MAAM,EAAE,QAAQ,SAAS;AAAA,EACzB,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;AACxB,CAAC;AAOD,IAAM,wBAAwB,EAAE,OAAO;AAAA,EACtC,MAAM,EAAE,QAAQ,WAAW;AAAA,EAC3B,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;AACxB,CAAC;AAMD,IAAM,wBAAwB,EAAE,OAAO;AAAA,EACtC,MAAM,EAAE,QAAQ,WAAW;AAAA,EAC3B,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;AACxB,CAAC;AAEM,IAAM,uBAAuB,EAAE,mBAAmB,QAAQ;AAAA,EAChE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,CAAC;AAwBM,IAAM,sBAET;AAAA,EACH,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,UAAU;AAAA,EACV,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AACZ;AAGO,SAAS,kBAAkB,MAAuC;AACxE,SAAO,oBAAoB,IAAI;AAChC;AAWO,IAAM,sBAAsB,EAAE,OAAO;AAAA,EAC3C,QAAQ;AAAA,EACR,YAAY,EAAE,KAAK,CAAC,QAAQ,KAAK,CAAC,EAAE,SAAS;AAC9C,CAAC;AAeM,IAAM,yBAAyB,EAAE,OAAO;AAAA,EAC9C,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAC1C,CAAC;AAQD,IAAM,iBAAiB,EAAE,OAAO;AAAA,EAC/B,MAAM,EAAE,QAAQ,MAAM;AAAA,EACtB,MAAM;AAAA,EACN,SAAS,EAAE,MAAM,kBAAkB,EAAE,IAAI,CAAC;AAAA,EAC1C,SAAS,EAAE,MAAM,oBAAoB,EAAE,QAAQ,CAAC,CAAC;AAClD,CAAC;AAED,IAAM,oBAAoB,EAAE,OAAO;AAAA,EAClC,MAAM,EAAE,QAAQ,SAAS;AAAA,EACzB,SAAS;AAAA,EACT,SAAS,EAAE,MAAM,kBAAkB,EAAE,IAAI,CAAC;AAAA,EAC1C,SAAS,EAAE,MAAM,oBAAoB,EAAE,QAAQ,CAAC,CAAC;AAClD,CAAC;AASM,IAAM,wBAAwB,EAAE,mBAAmB,QAAQ;AAAA,EACjE;AAAA,EACA;AACD,CAAC;","names":[]}
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  EnvEncryptionKey
3
3
  } from "./chunk-IP4OO26U.js";
4
- import {
5
- AuthController
6
- } from "./chunk-SZVPIHWE.js";
7
4
  import {
8
5
  DrizzleOAuthStateStore
9
6
  } from "./chunk-N5OTOWTP.js";
10
7
  import {
11
8
  MemoryOAuthStateStore
12
9
  } from "./chunk-QLTJSCE6.js";
10
+ import {
11
+ AuthController
12
+ } from "./chunk-SZVPIHWE.js";
13
13
  import {
14
14
  AUTH_OPTIONS,
15
15
  ENCRYPTION_KEY,
@@ -89,4 +89,4 @@ AuthModule = __decorateClass([
89
89
  export {
90
90
  AuthModule
91
91
  };
92
- //# sourceMappingURL=chunk-T6SCOJF4.js.map
92
+ //# sourceMappingURL=chunk-7LKAMLV4.js.map
@@ -1,15 +1,15 @@
1
- import {
2
- MemoryJobStore
3
- } from "./chunk-SNQ3TOWP.js";
4
- import {
5
- MissingTenantIdError
6
- } from "./chunk-T4BIIU5E.js";
7
1
  import {
8
2
  clampLimit,
9
3
  decodeKeysetCursor,
10
4
  encodeKeysetCursor,
11
5
  toJobRunSummary
12
6
  } from "./chunk-L3LZWWSX.js";
7
+ import {
8
+ MemoryJobStore
9
+ } from "./chunk-SNQ3TOWP.js";
10
+ import {
11
+ MissingTenantIdError
12
+ } from "./chunk-T4BIIU5E.js";
13
13
  import {
14
14
  JOBS_MULTI_TENANT,
15
15
  JOB_ORCHESTRATOR
@@ -209,4 +209,4 @@ function compareBy(a, b, order) {
209
209
  export {
210
210
  MemoryJobRunService
211
211
  };
212
- //# sourceMappingURL=chunk-BHZP6LOV.js.map
212
+ //# sourceMappingURL=chunk-CDLWYZVQ.js.map
@@ -1,6 +1,3 @@
1
- import {
2
- NoopAnalyticsBackend
3
- } from "./chunk-J37YWU7Y.js";
4
1
  import {
5
2
  CubeAnalyticsBackend
6
3
  } from "./chunk-7B3RYX45.js";
@@ -9,6 +6,9 @@ import {
9
6
  CUBE_API_SECRET,
10
7
  CUBE_API_URL
11
8
  } from "./chunk-6I7ULIN6.js";
9
+ import {
10
+ NoopAnalyticsBackend
11
+ } from "./chunk-J37YWU7Y.js";
12
12
  import {
13
13
  __decorateClass
14
14
  } from "./chunk-2E224ZSN.js";
@@ -50,4 +50,4 @@ AnalyticsModule = __decorateClass([
50
50
  export {
51
51
  AnalyticsModule
52
52
  };
53
- //# sourceMappingURL=chunk-DKKFTHHI.js.map
53
+ //# sourceMappingURL=chunk-CZQUOIDY.js.map
@@ -1,12 +1,12 @@
1
- import {
2
- INTEGRATION_MULTI_TENANT
3
- } from "./chunk-S7C6TIIF.js";
4
1
  import {
5
2
  assertTenantId
6
3
  } from "./chunk-MZ6GV4YF.js";
7
4
  import {
8
5
  integrationSubscriptions
9
6
  } from "./chunk-HNWZFNKP.js";
7
+ import {
8
+ INTEGRATION_MULTI_TENANT
9
+ } from "./chunk-S7C6TIIF.js";
10
10
  import {
11
11
  DRIZZLE
12
12
  } from "./chunk-U64T4YZE.js";
@@ -97,4 +97,4 @@ PostgresCursorStore = __decorateClass([
97
97
  export {
98
98
  PostgresCursorStore
99
99
  };
100
- //# sourceMappingURL=chunk-XWBK3XJK.js.map
100
+ //# sourceMappingURL=chunk-DCCZB4UC.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BRIDGE_DELIVERY_JOB_TYPE
3
- } from "./chunk-DRCLNYH7.js";
3
+ } from "./chunk-NXNVTXKG.js";
4
4
  import {
5
5
  bridgeDelivery
6
6
  } from "./chunk-2TVVBC53.js";
@@ -151,4 +151,4 @@ BridgeOutboxDrainHook = __decorateClass([
151
151
  export {
152
152
  BridgeOutboxDrainHook
153
153
  };
154
- //# sourceMappingURL=chunk-EBKVKN75.js.map
154
+ //# sourceMappingURL=chunk-DTXH24LR.js.map
@@ -1,13 +1,9 @@
1
1
  import {
2
2
  JobWorker
3
- } from "./chunk-XDIIVIIK.js";
3
+ } from "./chunk-OITTYGJS.js";
4
4
  import {
5
5
  JobsDomainModule
6
- } from "./chunk-3RWMQC3K.js";
7
- import {
8
- BootValidationError,
9
- ReservedPoolViolationError
10
- } from "./chunk-T4BIIU5E.js";
6
+ } from "./chunk-3MAZ4TQH.js";
11
7
  import {
12
8
  BULLMQ_CONNECTION,
13
9
  BULLMQ_RESOLVED_CONFIG,
@@ -18,14 +14,18 @@ import {
18
14
  allPoolNames,
19
15
  loadPoolConfig
20
16
  } from "./chunk-RHVN6NA7.js";
17
+ import {
18
+ BootValidationError,
19
+ ReservedPoolViolationError
20
+ } from "./chunk-T4BIIU5E.js";
21
+ import {
22
+ HandlerRegistry
23
+ } from "./chunk-CO6LUM72.js";
21
24
  import {
22
25
  JOB_ORCHESTRATOR,
23
26
  JOB_RUN_SERVICE,
24
27
  JOB_STEP_SERVICE
25
28
  } from "./chunk-ZPL74UQN.js";
26
- import {
27
- HandlerRegistry
28
- } from "./chunk-CO6LUM72.js";
29
29
  import {
30
30
  tokenKey
31
31
  } from "./chunk-GYGNEQSC.js";
@@ -290,4 +290,4 @@ export {
290
290
  JobWorkerOrchestrator,
291
291
  JobWorkerModule
292
292
  };
293
- //# sourceMappingURL=chunk-RUYLXR5F.js.map
293
+ //# sourceMappingURL=chunk-GJDEPTPY.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  DetectionConfigSchema
3
- } from "./chunk-3NMCDN7L.js";
3
+ } from "./chunk-5TK7MEN4.js";
4
4
 
5
5
  // src/parser/load-entities.ts
6
6
  import { resolve as resolve2 } from "path";
@@ -3807,6 +3807,15 @@ function formatMermaidGraph(result) {
3807
3807
  }
3808
3808
 
3809
3809
  // src/patterns/library/activity.pattern.ts
3810
+ import { z as z6 } from "zod";
3811
+ var ActivityPatternConfigSchema = z6.object({
3812
+ /** Subject entity name → derives the FK column `<subject>_id`. */
3813
+ subject: z6.string().optional(),
3814
+ /** Explicit snake_case FK column, when it does not follow `<subject>_id`. */
3815
+ subjectColumn: z6.string().optional(),
3816
+ /** snake_case recency-ordering column; defaults to `occurred_at`. */
3817
+ occurredAt: z6.string().optional()
3818
+ }).strict();
3810
3819
  var ActivityPattern = definePattern({
3811
3820
  name: "Activity",
3812
3821
  extends: ["Base"],
@@ -3814,15 +3823,16 @@ var ActivityPattern = definePattern({
3814
3823
  serviceClass: "ActivityEntityService",
3815
3824
  repositoryImport: "@shared/base-classes/activity-entity-repository",
3816
3825
  serviceImport: "@shared/base-classes/activity-entity-service",
3826
+ configSchema: ActivityPatternConfigSchema,
3817
3827
  repositoryInheritedMethods: [
3818
3828
  "findById, findByIds, list, count, exists, create, update, delete, upsertMany",
3819
- "findByDateRange, findByUserId, findByOpportunityId, findRecentByOpportunityId"
3829
+ "findByDateRange, findByUserId, findBySubjectId, findRecentBySubjectId"
3820
3830
  ],
3821
3831
  serviceInheritedMethods: [
3822
3832
  "findById, findByIds, list, count, exists, create, update, delete",
3823
- "findByDateRange, findByUserId, findByOpportunityId, findRecentByOpportunityId"
3833
+ "findByDateRange, findByUser, findBySubject, findRecent"
3824
3834
  ],
3825
- description: "Time-bounded interaction entities \u2014 date-range + opportunity scoped lookups"
3835
+ description: "Subject-scoped interaction entities \u2014 date-range + actor + config-driven subject lookups"
3826
3836
  });
3827
3837
 
3828
3838
  // src/patterns/library/base.pattern.ts
@@ -3842,8 +3852,8 @@ var BasePattern = definePattern({
3842
3852
  });
3843
3853
 
3844
3854
  // src/patterns/library/junction.pattern.ts
3845
- import { z as z6 } from "zod";
3846
- var JunctionPatternConfigSchema = z6.object({}).strict();
3855
+ import { z as z7 } from "zod";
3856
+ var JunctionPatternConfigSchema = z7.object({}).strict();
3847
3857
  var JunctionPattern = definePattern({
3848
3858
  name: "Junction",
3849
3859
  description: "Explicit many-to-many junction with role + temporal + sourcing metadata",
@@ -4039,4 +4049,4 @@ export {
4039
4049
  analyzeDomain,
4040
4050
  validateEntities
4041
4051
  };
4042
- //# sourceMappingURL=chunk-32DOFN3T.js.map
4052
+ //# sourceMappingURL=chunk-IOQMMH6C.js.map