@openhi/constructs 0.0.111 → 0.0.113

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 (111) hide show
  1. package/lib/chunk-23PUSHBV.mjs +24 -0
  2. package/lib/chunk-23PUSHBV.mjs.map +1 -0
  3. package/lib/{chunk-7FUAMZOF.mjs → chunk-53OHXLIL.mjs} +3 -3
  4. package/lib/chunk-6NBGYGFL.mjs +1803 -0
  5. package/lib/chunk-6NBGYGFL.mjs.map +1 -0
  6. package/lib/chunk-7RZHFI77.mjs +22 -0
  7. package/lib/chunk-7RZHFI77.mjs.map +1 -0
  8. package/lib/{chunk-7Q2IJ2J5.mjs → chunk-CUUKXDB2.mjs} +6 -6
  9. package/lib/chunk-FYHBHHWK.mjs +47 -0
  10. package/lib/chunk-FYHBHHWK.mjs.map +1 -0
  11. package/lib/{chunk-MULKGFIJ.mjs → chunk-GBDIGTNV.mjs} +165 -10
  12. package/lib/chunk-GBDIGTNV.mjs.map +1 -0
  13. package/lib/chunk-HQ67J7BP.mjs +199 -0
  14. package/lib/chunk-HQ67J7BP.mjs.map +1 -0
  15. package/lib/{chunk-AJ3G3THO.mjs → chunk-KO64HPWQ.mjs} +2 -2
  16. package/lib/{chunk-BB5MK4L3.mjs → chunk-KSFC72TT.mjs} +3 -3
  17. package/lib/{chunk-2TPJ6HOF.mjs → chunk-NZRW7ROK.mjs} +72 -54
  18. package/lib/chunk-NZRW7ROK.mjs.map +1 -0
  19. package/lib/chunk-QJDHVMKT.mjs +117 -0
  20. package/lib/chunk-QJDHVMKT.mjs.map +1 -0
  21. package/lib/{chunk-IS4VQRI4.mjs → chunk-QMBJ4VHC.mjs} +12 -47
  22. package/lib/chunk-QMBJ4VHC.mjs.map +1 -0
  23. package/lib/chunk-TRY7JGWO.mjs +16 -0
  24. package/lib/chunk-TRY7JGWO.mjs.map +1 -0
  25. package/lib/chunk-W4KR4CSL.mjs +236 -0
  26. package/lib/chunk-W4KR4CSL.mjs.map +1 -0
  27. package/lib/{chunk-AGF3RAAZ.mjs → chunk-WPCBVDFZ.mjs} +2 -2
  28. package/lib/chunk-WQWFVEVX.mjs +66 -0
  29. package/lib/chunk-WQWFVEVX.mjs.map +1 -0
  30. package/lib/{chunk-SYBADQXI.mjs → chunk-ZM4GDHHC.mjs} +77 -2
  31. package/lib/chunk-ZM4GDHHC.mjs.map +1 -0
  32. package/lib/delete-chunk.handler.d.mts +29 -0
  33. package/lib/delete-chunk.handler.d.ts +29 -0
  34. package/lib/delete-chunk.handler.js +2716 -0
  35. package/lib/delete-chunk.handler.js.map +1 -0
  36. package/lib/delete-chunk.handler.mjs +47 -0
  37. package/lib/delete-chunk.handler.mjs.map +1 -0
  38. package/lib/events-CjS-sm0W.d.mts +107 -0
  39. package/lib/events-CjS-sm0W.d.ts +107 -0
  40. package/lib/events-Da_cFgtc.d.mts +208 -0
  41. package/lib/events-Da_cFgtc.d.ts +208 -0
  42. package/lib/finalize.handler.d.mts +35 -0
  43. package/lib/finalize.handler.d.ts +35 -0
  44. package/lib/finalize.handler.js +875 -0
  45. package/lib/finalize.handler.js.map +1 -0
  46. package/lib/finalize.handler.mjs +166 -0
  47. package/lib/finalize.handler.mjs.map +1 -0
  48. package/lib/index.d.mts +189 -2
  49. package/lib/index.d.ts +500 -3
  50. package/lib/index.js +1753 -174
  51. package/lib/index.js.map +1 -1
  52. package/lib/index.mjs +571 -17
  53. package/lib/index.mjs.map +1 -1
  54. package/lib/list-chunks.handler.d.mts +28 -0
  55. package/lib/list-chunks.handler.d.ts +28 -0
  56. package/lib/list-chunks.handler.js +2746 -0
  57. package/lib/list-chunks.handler.js.map +1 -0
  58. package/lib/list-chunks.handler.mjs +54 -0
  59. package/lib/list-chunks.handler.mjs.map +1 -0
  60. package/lib/platform-deploy-bridge.handler.js +76 -1
  61. package/lib/platform-deploy-bridge.handler.js.map +1 -1
  62. package/lib/platform-deploy-bridge.handler.mjs +1 -1
  63. package/lib/pre-token-generation.handler.js +1106 -155
  64. package/lib/pre-token-generation.handler.js.map +1 -1
  65. package/lib/pre-token-generation.handler.mjs +6 -4
  66. package/lib/pre-token-generation.handler.mjs.map +1 -1
  67. package/lib/provision-default-workspace.handler.js +1529 -142
  68. package/lib/provision-default-workspace.handler.js.map +1 -1
  69. package/lib/provision-default-workspace.handler.mjs +8 -4
  70. package/lib/provision-default-workspace.handler.mjs.map +1 -1
  71. package/lib/rename-finalize.handler.d.mts +30 -0
  72. package/lib/rename-finalize.handler.d.ts +30 -0
  73. package/lib/rename-finalize.handler.js +795 -0
  74. package/lib/rename-finalize.handler.js.map +1 -0
  75. package/lib/rename-finalize.handler.mjs +90 -0
  76. package/lib/rename-finalize.handler.mjs.map +1 -0
  77. package/lib/rename-list-targets.handler.d.mts +26 -0
  78. package/lib/rename-list-targets.handler.d.ts +26 -0
  79. package/lib/rename-list-targets.handler.js +2985 -0
  80. package/lib/rename-list-targets.handler.js.map +1 -0
  81. package/lib/rename-list-targets.handler.mjs +431 -0
  82. package/lib/rename-list-targets.handler.mjs.map +1 -0
  83. package/lib/rename-rewrite-chunk.handler.d.mts +35 -0
  84. package/lib/rename-rewrite-chunk.handler.d.ts +35 -0
  85. package/lib/rename-rewrite-chunk.handler.js +2021 -0
  86. package/lib/rename-rewrite-chunk.handler.js.map +1 -0
  87. package/lib/rename-rewrite-chunk.handler.mjs +27 -0
  88. package/lib/rename-rewrite-chunk.handler.mjs.map +1 -0
  89. package/lib/rest-api-lambda.handler.js +4021 -932
  90. package/lib/rest-api-lambda.handler.js.map +1 -1
  91. package/lib/rest-api-lambda.handler.mjs +1786 -80
  92. package/lib/rest-api-lambda.handler.mjs.map +1 -1
  93. package/lib/seed-demo-data.handler.js +1588 -124
  94. package/lib/seed-demo-data.handler.js.map +1 -1
  95. package/lib/seed-demo-data.handler.mjs +10 -6
  96. package/lib/seed-system-data.handler.js +1179 -155
  97. package/lib/seed-system-data.handler.js.map +1 -1
  98. package/lib/seed-system-data.handler.mjs +5 -4
  99. package/lib/seed-system-data.handler.mjs.map +1 -1
  100. package/package.json +2 -2
  101. package/lib/chunk-2TPJ6HOF.mjs.map +0 -1
  102. package/lib/chunk-IS4VQRI4.mjs.map +0 -1
  103. package/lib/chunk-MULKGFIJ.mjs.map +0 -1
  104. package/lib/chunk-QR5JVSCF.mjs +0 -862
  105. package/lib/chunk-QR5JVSCF.mjs.map +0 -1
  106. package/lib/chunk-SYBADQXI.mjs.map +0 -1
  107. /package/lib/{chunk-7FUAMZOF.mjs.map → chunk-53OHXLIL.mjs.map} +0 -0
  108. /package/lib/{chunk-7Q2IJ2J5.mjs.map → chunk-CUUKXDB2.mjs.map} +0 -0
  109. /package/lib/{chunk-AJ3G3THO.mjs.map → chunk-KO64HPWQ.mjs.map} +0 -0
  110. /package/lib/{chunk-BB5MK4L3.mjs.map → chunk-KSFC72TT.mjs.map} +0 -0
  111. /package/lib/{chunk-AGF3RAAZ.mjs.map → chunk-WPCBVDFZ.mjs.map} +0 -0
@@ -0,0 +1,107 @@
1
+ /**
2
+ * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/owning-delete-cascade/events.md
3
+ *
4
+ * Shared event-shape constants for the TR-022 owning-entity hard-delete
5
+ * cascade. The cascade's input detail-type (on the data event bus) and
6
+ * its two terminal detail-types (on the ops event bus) are owned by
7
+ * `@openhi/workflows`; this module re-imports them so the workflow
8
+ * construct can wire the EventBridge rule and the terminal publisher
9
+ * from a single place.
10
+ */
11
+
12
+ /**
13
+ * Stable logical name registered with the shared `WorkflowDedupTable`
14
+ * (TR-015). The state machine's `DedupCheck` state writes a row keyed
15
+ * by `(consumerName, eventId, attempt)` to absorb EventBridge retries.
16
+ */
17
+ declare const OWNING_DELETE_CASCADE_CONSUMER_NAME: "owning-delete-cascade";
18
+ /**
19
+ * Map-state max concurrency. Per the ADR-018 implementation guide
20
+ * section 4: inline Map (NOT Distributed Map — that lives on TR-023's
21
+ * rename cascade), tunable via the construct's `cascadeMapConcurrency`
22
+ * prop. Operators may scale this down on first rollout.
23
+ */
24
+ declare const OWNING_DELETE_CASCADE_DEFAULT_CONCURRENCY: 8;
25
+ /**
26
+ * Stuck-cascade alarm threshold. Per the implementation guide section
27
+ * 4 "Observability" — operator-tunable via
28
+ * `stuckCascadeThresholdMinutes` on the construct prop.
29
+ */
30
+ declare const OWNING_DELETE_CASCADE_STUCK_THRESHOLD_MINUTES: 15;
31
+ /**
32
+ * Inputs each cascade Map iteration receives. The state machine
33
+ * builds one of these per chunk and passes them in via `ItemsPath`.
34
+ * The handler then issues a single `TransactWriteItems` for the
35
+ * entire chunk.
36
+ */
37
+ interface CascadeChunkInput {
38
+ /** Owner identity carried through every step for observability. */
39
+ readonly ownerType: "Workspace" | "User";
40
+ readonly ownerId: string;
41
+ readonly tenantId?: string;
42
+ /** Rows to delete in this chunk. Length must be 1..100. */
43
+ readonly rows: ReadonlyArray<{
44
+ readonly entity: string;
45
+ readonly key: Record<string, string>;
46
+ }>;
47
+ /**
48
+ * Idempotency token uniquely identifying this chunk within the
49
+ * cascade execution. Forwarded to `executeMultiWrite` so replayed
50
+ * chunks land idempotently (per AWS SDK `ClientRequestToken`).
51
+ */
52
+ readonly chunkToken: string;
53
+ }
54
+ /** Inputs the cascade list-and-chunk step receives. */
55
+ interface CascadeListInput {
56
+ readonly ownerType: "Workspace" | "User";
57
+ readonly ownerId: string;
58
+ readonly tenantId?: string;
59
+ /** Per-entity cursor map from the previous page (start of run is `{}`). */
60
+ readonly cursors?: Record<string, string | null>;
61
+ /**
62
+ * Cumulative `projectionsRemoved` count carried forward across
63
+ * pages — emitted on the terminal `complete` event.
64
+ */
65
+ readonly projectionsRemoved?: number;
66
+ /** Cumulative `chunkCount` carried forward across pages. */
67
+ readonly chunkCount?: number;
68
+ }
69
+ /** Outputs the cascade list-and-chunk step emits to feed the Map state. */
70
+ interface CascadeListOutput {
71
+ readonly ownerType: "Workspace" | "User";
72
+ readonly ownerId: string;
73
+ readonly tenantId?: string;
74
+ readonly cursors: Record<string, string | null>;
75
+ readonly chunks: ReadonlyArray<CascadeChunkInput>;
76
+ readonly exhausted: boolean;
77
+ readonly projectionsRemoved: number;
78
+ readonly chunkCount: number;
79
+ }
80
+ /** Inputs the cascade finalize step receives. */
81
+ interface CascadeFinalizeInput {
82
+ readonly ownerType: "Workspace" | "User";
83
+ readonly ownerId: string;
84
+ readonly tenantId?: string;
85
+ readonly projectionsRemoved: number;
86
+ readonly chunkCount: number;
87
+ readonly startedAt: string;
88
+ /** Optional eventId / correlation carried through the run for ADR-016 envelope. */
89
+ readonly eventId?: string;
90
+ readonly correlationId?: string;
91
+ readonly causationId?: string;
92
+ }
93
+ /** Outputs the cascade finalize step emits (used by tests and telemetry). */
94
+ interface CascadeFinalizeOutput {
95
+ readonly ownerType: "Workspace" | "User";
96
+ readonly ownerId: string;
97
+ readonly tenantId?: string;
98
+ readonly projectionsRemoved: number;
99
+ readonly chunkCount: number;
100
+ readonly durationMs: number;
101
+ readonly completedAt: string;
102
+ readonly canonicalDeleted: boolean;
103
+ }
104
+ /** Env var the construct uses to inject the ops event bus name into the finalize Lambda. */
105
+ declare const OWNING_DELETE_OPS_EVENT_BUS_ENV_VAR: "OWNING_DELETE_OPS_EVENT_BUS_NAME";
106
+
107
+ export { type CascadeChunkInput as C, OWNING_DELETE_CASCADE_CONSUMER_NAME as O, type CascadeFinalizeInput as a, type CascadeFinalizeOutput as b, type CascadeListInput as c, type CascadeListOutput as d, OWNING_DELETE_CASCADE_DEFAULT_CONCURRENCY as e, OWNING_DELETE_CASCADE_STUCK_THRESHOLD_MINUTES as f, OWNING_DELETE_OPS_EVENT_BUS_ENV_VAR as g };
@@ -0,0 +1,107 @@
1
+ /**
2
+ * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/owning-delete-cascade/events.md
3
+ *
4
+ * Shared event-shape constants for the TR-022 owning-entity hard-delete
5
+ * cascade. The cascade's input detail-type (on the data event bus) and
6
+ * its two terminal detail-types (on the ops event bus) are owned by
7
+ * `@openhi/workflows`; this module re-imports them so the workflow
8
+ * construct can wire the EventBridge rule and the terminal publisher
9
+ * from a single place.
10
+ */
11
+
12
+ /**
13
+ * Stable logical name registered with the shared `WorkflowDedupTable`
14
+ * (TR-015). The state machine's `DedupCheck` state writes a row keyed
15
+ * by `(consumerName, eventId, attempt)` to absorb EventBridge retries.
16
+ */
17
+ declare const OWNING_DELETE_CASCADE_CONSUMER_NAME: "owning-delete-cascade";
18
+ /**
19
+ * Map-state max concurrency. Per the ADR-018 implementation guide
20
+ * section 4: inline Map (NOT Distributed Map — that lives on TR-023's
21
+ * rename cascade), tunable via the construct's `cascadeMapConcurrency`
22
+ * prop. Operators may scale this down on first rollout.
23
+ */
24
+ declare const OWNING_DELETE_CASCADE_DEFAULT_CONCURRENCY: 8;
25
+ /**
26
+ * Stuck-cascade alarm threshold. Per the implementation guide section
27
+ * 4 "Observability" — operator-tunable via
28
+ * `stuckCascadeThresholdMinutes` on the construct prop.
29
+ */
30
+ declare const OWNING_DELETE_CASCADE_STUCK_THRESHOLD_MINUTES: 15;
31
+ /**
32
+ * Inputs each cascade Map iteration receives. The state machine
33
+ * builds one of these per chunk and passes them in via `ItemsPath`.
34
+ * The handler then issues a single `TransactWriteItems` for the
35
+ * entire chunk.
36
+ */
37
+ interface CascadeChunkInput {
38
+ /** Owner identity carried through every step for observability. */
39
+ readonly ownerType: "Workspace" | "User";
40
+ readonly ownerId: string;
41
+ readonly tenantId?: string;
42
+ /** Rows to delete in this chunk. Length must be 1..100. */
43
+ readonly rows: ReadonlyArray<{
44
+ readonly entity: string;
45
+ readonly key: Record<string, string>;
46
+ }>;
47
+ /**
48
+ * Idempotency token uniquely identifying this chunk within the
49
+ * cascade execution. Forwarded to `executeMultiWrite` so replayed
50
+ * chunks land idempotently (per AWS SDK `ClientRequestToken`).
51
+ */
52
+ readonly chunkToken: string;
53
+ }
54
+ /** Inputs the cascade list-and-chunk step receives. */
55
+ interface CascadeListInput {
56
+ readonly ownerType: "Workspace" | "User";
57
+ readonly ownerId: string;
58
+ readonly tenantId?: string;
59
+ /** Per-entity cursor map from the previous page (start of run is `{}`). */
60
+ readonly cursors?: Record<string, string | null>;
61
+ /**
62
+ * Cumulative `projectionsRemoved` count carried forward across
63
+ * pages — emitted on the terminal `complete` event.
64
+ */
65
+ readonly projectionsRemoved?: number;
66
+ /** Cumulative `chunkCount` carried forward across pages. */
67
+ readonly chunkCount?: number;
68
+ }
69
+ /** Outputs the cascade list-and-chunk step emits to feed the Map state. */
70
+ interface CascadeListOutput {
71
+ readonly ownerType: "Workspace" | "User";
72
+ readonly ownerId: string;
73
+ readonly tenantId?: string;
74
+ readonly cursors: Record<string, string | null>;
75
+ readonly chunks: ReadonlyArray<CascadeChunkInput>;
76
+ readonly exhausted: boolean;
77
+ readonly projectionsRemoved: number;
78
+ readonly chunkCount: number;
79
+ }
80
+ /** Inputs the cascade finalize step receives. */
81
+ interface CascadeFinalizeInput {
82
+ readonly ownerType: "Workspace" | "User";
83
+ readonly ownerId: string;
84
+ readonly tenantId?: string;
85
+ readonly projectionsRemoved: number;
86
+ readonly chunkCount: number;
87
+ readonly startedAt: string;
88
+ /** Optional eventId / correlation carried through the run for ADR-016 envelope. */
89
+ readonly eventId?: string;
90
+ readonly correlationId?: string;
91
+ readonly causationId?: string;
92
+ }
93
+ /** Outputs the cascade finalize step emits (used by tests and telemetry). */
94
+ interface CascadeFinalizeOutput {
95
+ readonly ownerType: "Workspace" | "User";
96
+ readonly ownerId: string;
97
+ readonly tenantId?: string;
98
+ readonly projectionsRemoved: number;
99
+ readonly chunkCount: number;
100
+ readonly durationMs: number;
101
+ readonly completedAt: string;
102
+ readonly canonicalDeleted: boolean;
103
+ }
104
+ /** Env var the construct uses to inject the ops event bus name into the finalize Lambda. */
105
+ declare const OWNING_DELETE_OPS_EVENT_BUS_ENV_VAR: "OWNING_DELETE_OPS_EVENT_BUS_NAME";
106
+
107
+ export { type CascadeChunkInput as C, OWNING_DELETE_CASCADE_CONSUMER_NAME as O, type CascadeFinalizeInput as a, type CascadeFinalizeOutput as b, type CascadeListInput as c, type CascadeListOutput as d, OWNING_DELETE_CASCADE_DEFAULT_CONCURRENCY as e, OWNING_DELETE_CASCADE_STUCK_THRESHOLD_MINUTES as f, OWNING_DELETE_OPS_EVENT_BUS_ENV_VAR as g };
@@ -0,0 +1,208 @@
1
+ import { RenamableEntityType } from '@openhi/workflows';
2
+
3
+ /**
4
+ * Enumerate projection rows affected by a Tenant / User / Role rename
5
+ * for the TR-023 rename cascade.
6
+ *
7
+ * One page per call; the cascade state machine outer loop walks the
8
+ * returned `cursors` map back into this operation until every per-entity
9
+ * stream returns `null`. Each emitted row carries:
10
+ *
11
+ * - the projection-entity name (so the rewrite-chunk operation can map
12
+ * it to the correct ElectroDB entity in `executeMultiWrite`),
13
+ * - the **existing** composite key (used for the `delete` triple in the
14
+ * transact-write pair),
15
+ * - the **new** composite key (used for the `put` triple — same row
16
+ * identity but a rewritten SK when the SK encodes the renamed
17
+ * normalized name), and
18
+ * - the row's existing attributes (carried verbatim into the `put` so
19
+ * `summary`, `vid`, `lastUpdated`, etc. are preserved across the
20
+ * rewrite), with the renamed `denormalized<CarrierEntity>Name`
21
+ * replaced by the new display name.
22
+ *
23
+ * Per-entityType query plan (per the ADR-018 implementation guide § 5):
24
+ *
25
+ * - **User rename**: under `PK = USER#ID#<userId>` — Membership user-
26
+ * projection rows (patterns #3 + #4) and RoleAssignment user-projection
27
+ * rows (pattern #5). Workspace-side projection rows
28
+ * (membershipWorkspaceProjection #2 + roleAssignmentWorkspaceProjection
29
+ * #9) encode `<normalizedUserName>` in their SK; this operation
30
+ * discovers the affected workspaces from the user's pattern-#4
31
+ * memberships and queries each workspace partition for them.
32
+ * - **Role rename**: under every affected user partition — RoleAssignment
33
+ * user-projection rows (pattern #5) sort on `<normalizedRoleName>` and
34
+ * need a SK rewrite. RoleAssignment canonical (pattern #8) and
35
+ * workspace-projection (pattern #9) sort on raw `<roleId>` so only the
36
+ * denormalized attr changes (no SK rewrite). The affected user-ids
37
+ * are discovered via the canonical RoleAssignment GSI1 (`<roleId>#`
38
+ * prefix).
39
+ * - **Tenant rename**: only `denormalizedTenantName` updates — SKs do
40
+ * not carry tenant-name; the row identity is preserved. Affected user-
41
+ * ids are discovered via the canonical Membership GSI1 page.
42
+ *
43
+ * For #1023 the User-rename path is implemented in full; the Tenant /
44
+ * Role discovery hooks are scaffolded with the right query shape and
45
+ * cursor map but only walk one canonical discovery batch per call (the
46
+ * cascade outer loop pages through them). See § 5 of the implementation
47
+ * guide for the full matrix.
48
+ *
49
+ * @see .state/adr-018-implementation-guide.md § 5 (TR-023 Rename-Cascade Consumer Contract)
50
+ * @see .claude/rules/data-layer-layout.md
51
+ */
52
+
53
+ /**
54
+ * Projection-entity name keys this operation may emit. Each key maps to
55
+ * an entity in the control-plane service; the rewrite-chunk consumer
56
+ * forwards it to `executeMultiWrite` as the `entity` field on a triple.
57
+ */
58
+ declare const RENAME_CASCADE_PROJECTION_ENTITY: {
59
+ readonly MembershipUserProjection: "membershipUserProjection";
60
+ readonly MembershipWorkspaceProjection: "membershipWorkspaceProjection";
61
+ readonly RoleAssignmentUserProjection: "roleAssignmentUserProjection";
62
+ readonly RoleAssignmentWorkspaceProjection: "roleAssignmentWorkspaceProjection";
63
+ };
64
+ type RenameCascadeProjectionEntity = (typeof RENAME_CASCADE_PROJECTION_ENTITY)[keyof typeof RENAME_CASCADE_PROJECTION_ENTITY];
65
+ /**
66
+ * One row to rewrite — the cascade rewrite-chunk operation turns each
67
+ * entry into a `delete oldKey` + `put newPayload` transact-write pair.
68
+ *
69
+ * `oldKey` and `newKey` differ only in the SK segment when the SK
70
+ * encodes a normalized form of the renamed name. For Tenant rename and
71
+ * for SK-stable RoleAssignment projections (canonical pattern #8 and
72
+ * workspace pattern #9 under a Role rename), `oldKey === newKey` and
73
+ * the rewrite collapses to a single `put` overwrite.
74
+ */
75
+ interface RenameCascadeRewriteTarget {
76
+ readonly entity: RenameCascadeProjectionEntity;
77
+ /** Composite key payload for the existing row. */
78
+ readonly oldKey: Record<string, string>;
79
+ /** Composite key payload for the rewritten row. */
80
+ readonly newKey: Record<string, string>;
81
+ /**
82
+ * Full row payload to write at `newKey` — carries the existing
83
+ * `summary`, `vid`, `lastUpdated`, and discriminating fields, with
84
+ * the renamed `denormalized<CarrierEntity>Name` swapped to the new
85
+ * display name.
86
+ */
87
+ readonly newItem: Record<string, unknown>;
88
+ /**
89
+ * `true` when `oldKey` and `newKey` differ — the rewrite must atomic
90
+ * delete the old row and put the new row in the same transaction.
91
+ * `false` when only the denormalized attr changes — a single `put`
92
+ * overwrite is sufficient.
93
+ */
94
+ readonly skRewriteRequired: boolean;
95
+ }
96
+
97
+ /**
98
+ * Shared event-shape constants for the TR-023 rename-cascade consumer.
99
+ * The cascade's input detail-type (on the data event bus) and its two
100
+ * terminal detail-types (on the ops event bus) are owned by
101
+ * `@openhi/workflows`; this module re-imports them so the workflow
102
+ * construct can wire the EventBridge rule and the terminal publisher
103
+ * from a single place.
104
+ *
105
+ * @see .state/adr-018-implementation-guide.md section 5
106
+ */
107
+
108
+ /**
109
+ * Stable logical name registered with the shared `WorkflowDedupTable`
110
+ * (TR-015). The state machine's `DedupCheck` state writes a row keyed
111
+ * by `(consumerName, eventId, attempt)` to absorb EventBridge retries.
112
+ */
113
+ declare const RENAME_CASCADE_CONSUMER_NAME: "rename-cascade";
114
+ /**
115
+ * Distributed-Map max concurrency. Per the ADR-018 implementation guide
116
+ * section 5: Distributed Map (NOT inline — TR-022 owning-delete uses
117
+ * inline), tunable via the construct's `cascadeMapConcurrency` prop.
118
+ * Operators may scale this down on first rollout.
119
+ */
120
+ declare const RENAME_CASCADE_DEFAULT_CONCURRENCY: 10;
121
+ /**
122
+ * `CascadeFailed` alarm threshold — fires when ExecutionsFailed exceeds
123
+ * the value over the configured period. Per the implementation guide
124
+ * section 5 "Alarm thresholds" table.
125
+ */
126
+ declare const RENAME_CASCADE_FAILED_THRESHOLD: 0;
127
+ /**
128
+ * `CascadeSlow` alarm threshold (in seconds) — fires when ExecutionTime
129
+ * p99 exceeds the value. Per the implementation guide section 5.
130
+ */
131
+ declare const RENAME_CASCADE_SLOW_THRESHOLD_SECONDS: 300;
132
+ /**
133
+ * Inputs the cascade list-targets step receives. Most fields come
134
+ * straight off the `ControlPlaneRenameV1` envelope payload; `cursors`
135
+ * threads through the outer loop.
136
+ */
137
+ interface RenameCascadeListInput {
138
+ readonly entityType: RenamableEntityType;
139
+ readonly entityId: string;
140
+ readonly tenantId?: string;
141
+ readonly oldName: string;
142
+ readonly newName: string;
143
+ readonly oldNormalizedName: string;
144
+ readonly newNormalizedName: string;
145
+ readonly cursors?: Record<string, string | null>;
146
+ /** Cumulative `itemsRewritten` carried forward across pages. */
147
+ readonly itemsRewritten?: number;
148
+ /** Cumulative `chunkCount` carried forward across pages. */
149
+ readonly chunkCount?: number;
150
+ }
151
+ /** Inputs the cascade rewrite-chunk step receives — one chunk per Map iteration. */
152
+ interface RenameCascadeChunkInput {
153
+ readonly entityType: RenamableEntityType;
154
+ readonly entityId: string;
155
+ readonly tenantId?: string;
156
+ /** Targets to rewrite in this transaction. Length must be 1..50. */
157
+ readonly targets: ReadonlyArray<RenameCascadeRewriteTarget>;
158
+ /**
159
+ * Idempotency token uniquely identifying this chunk within the
160
+ * cascade execution. Forwarded to `executeMultiWrite` so replayed
161
+ * chunks land idempotently.
162
+ */
163
+ readonly chunkToken: string;
164
+ }
165
+ /** Outputs the cascade list-targets step emits to feed the Distributed Map state. */
166
+ interface RenameCascadeListOutput {
167
+ readonly entityType: RenamableEntityType;
168
+ readonly entityId: string;
169
+ readonly tenantId?: string;
170
+ readonly oldName: string;
171
+ readonly newName: string;
172
+ readonly oldNormalizedName: string;
173
+ readonly newNormalizedName: string;
174
+ readonly cursors: Record<string, string | null>;
175
+ readonly chunks: ReadonlyArray<RenameCascadeChunkInput>;
176
+ readonly exhausted: boolean;
177
+ readonly itemsRewritten: number;
178
+ readonly chunkCount: number;
179
+ }
180
+ /** Inputs the cascade finalize step receives. */
181
+ interface RenameCascadeFinalizeInput {
182
+ readonly entityType: RenamableEntityType;
183
+ readonly entityId: string;
184
+ readonly tenantId?: string;
185
+ readonly newName: string;
186
+ readonly itemsRewritten: number;
187
+ readonly chunkCount: number;
188
+ readonly startedAt: string;
189
+ /** Optional eventId / correlation for ADR-016 envelope chaining. */
190
+ readonly eventId?: string;
191
+ readonly correlationId?: string;
192
+ readonly causationId?: string;
193
+ }
194
+ /** Outputs the cascade finalize step emits (used by tests + telemetry). */
195
+ interface RenameCascadeFinalizeOutput {
196
+ readonly entityType: RenamableEntityType;
197
+ readonly entityId: string;
198
+ readonly tenantId?: string;
199
+ readonly newName: string;
200
+ readonly itemsRewritten: number;
201
+ readonly chunkCount: number;
202
+ readonly durationMs: number;
203
+ readonly completedAt: string;
204
+ }
205
+ /** Env var the construct uses to inject the ops event bus name into the finalize Lambda. */
206
+ declare const RENAME_CASCADE_OPS_EVENT_BUS_ENV_VAR: "RENAME_CASCADE_OPS_EVENT_BUS_NAME";
207
+
208
+ export { RENAME_CASCADE_CONSUMER_NAME as R, RENAME_CASCADE_DEFAULT_CONCURRENCY as a, RENAME_CASCADE_FAILED_THRESHOLD as b, RENAME_CASCADE_OPS_EVENT_BUS_ENV_VAR as c, RENAME_CASCADE_SLOW_THRESHOLD_SECONDS as d, type RenameCascadeChunkInput as e, type RenameCascadeFinalizeInput as f, type RenameCascadeFinalizeOutput as g, type RenameCascadeListInput as h, type RenameCascadeListOutput as i };
@@ -0,0 +1,208 @@
1
+ import { RenamableEntityType } from '@openhi/workflows';
2
+
3
+ /**
4
+ * Enumerate projection rows affected by a Tenant / User / Role rename
5
+ * for the TR-023 rename cascade.
6
+ *
7
+ * One page per call; the cascade state machine outer loop walks the
8
+ * returned `cursors` map back into this operation until every per-entity
9
+ * stream returns `null`. Each emitted row carries:
10
+ *
11
+ * - the projection-entity name (so the rewrite-chunk operation can map
12
+ * it to the correct ElectroDB entity in `executeMultiWrite`),
13
+ * - the **existing** composite key (used for the `delete` triple in the
14
+ * transact-write pair),
15
+ * - the **new** composite key (used for the `put` triple — same row
16
+ * identity but a rewritten SK when the SK encodes the renamed
17
+ * normalized name), and
18
+ * - the row's existing attributes (carried verbatim into the `put` so
19
+ * `summary`, `vid`, `lastUpdated`, etc. are preserved across the
20
+ * rewrite), with the renamed `denormalized<CarrierEntity>Name`
21
+ * replaced by the new display name.
22
+ *
23
+ * Per-entityType query plan (per the ADR-018 implementation guide § 5):
24
+ *
25
+ * - **User rename**: under `PK = USER#ID#<userId>` — Membership user-
26
+ * projection rows (patterns #3 + #4) and RoleAssignment user-projection
27
+ * rows (pattern #5). Workspace-side projection rows
28
+ * (membershipWorkspaceProjection #2 + roleAssignmentWorkspaceProjection
29
+ * #9) encode `<normalizedUserName>` in their SK; this operation
30
+ * discovers the affected workspaces from the user's pattern-#4
31
+ * memberships and queries each workspace partition for them.
32
+ * - **Role rename**: under every affected user partition — RoleAssignment
33
+ * user-projection rows (pattern #5) sort on `<normalizedRoleName>` and
34
+ * need a SK rewrite. RoleAssignment canonical (pattern #8) and
35
+ * workspace-projection (pattern #9) sort on raw `<roleId>` so only the
36
+ * denormalized attr changes (no SK rewrite). The affected user-ids
37
+ * are discovered via the canonical RoleAssignment GSI1 (`<roleId>#`
38
+ * prefix).
39
+ * - **Tenant rename**: only `denormalizedTenantName` updates — SKs do
40
+ * not carry tenant-name; the row identity is preserved. Affected user-
41
+ * ids are discovered via the canonical Membership GSI1 page.
42
+ *
43
+ * For #1023 the User-rename path is implemented in full; the Tenant /
44
+ * Role discovery hooks are scaffolded with the right query shape and
45
+ * cursor map but only walk one canonical discovery batch per call (the
46
+ * cascade outer loop pages through them). See § 5 of the implementation
47
+ * guide for the full matrix.
48
+ *
49
+ * @see .state/adr-018-implementation-guide.md § 5 (TR-023 Rename-Cascade Consumer Contract)
50
+ * @see .claude/rules/data-layer-layout.md
51
+ */
52
+
53
+ /**
54
+ * Projection-entity name keys this operation may emit. Each key maps to
55
+ * an entity in the control-plane service; the rewrite-chunk consumer
56
+ * forwards it to `executeMultiWrite` as the `entity` field on a triple.
57
+ */
58
+ declare const RENAME_CASCADE_PROJECTION_ENTITY: {
59
+ readonly MembershipUserProjection: "membershipUserProjection";
60
+ readonly MembershipWorkspaceProjection: "membershipWorkspaceProjection";
61
+ readonly RoleAssignmentUserProjection: "roleAssignmentUserProjection";
62
+ readonly RoleAssignmentWorkspaceProjection: "roleAssignmentWorkspaceProjection";
63
+ };
64
+ type RenameCascadeProjectionEntity = (typeof RENAME_CASCADE_PROJECTION_ENTITY)[keyof typeof RENAME_CASCADE_PROJECTION_ENTITY];
65
+ /**
66
+ * One row to rewrite — the cascade rewrite-chunk operation turns each
67
+ * entry into a `delete oldKey` + `put newPayload` transact-write pair.
68
+ *
69
+ * `oldKey` and `newKey` differ only in the SK segment when the SK
70
+ * encodes a normalized form of the renamed name. For Tenant rename and
71
+ * for SK-stable RoleAssignment projections (canonical pattern #8 and
72
+ * workspace pattern #9 under a Role rename), `oldKey === newKey` and
73
+ * the rewrite collapses to a single `put` overwrite.
74
+ */
75
+ interface RenameCascadeRewriteTarget {
76
+ readonly entity: RenameCascadeProjectionEntity;
77
+ /** Composite key payload for the existing row. */
78
+ readonly oldKey: Record<string, string>;
79
+ /** Composite key payload for the rewritten row. */
80
+ readonly newKey: Record<string, string>;
81
+ /**
82
+ * Full row payload to write at `newKey` — carries the existing
83
+ * `summary`, `vid`, `lastUpdated`, and discriminating fields, with
84
+ * the renamed `denormalized<CarrierEntity>Name` swapped to the new
85
+ * display name.
86
+ */
87
+ readonly newItem: Record<string, unknown>;
88
+ /**
89
+ * `true` when `oldKey` and `newKey` differ — the rewrite must atomic
90
+ * delete the old row and put the new row in the same transaction.
91
+ * `false` when only the denormalized attr changes — a single `put`
92
+ * overwrite is sufficient.
93
+ */
94
+ readonly skRewriteRequired: boolean;
95
+ }
96
+
97
+ /**
98
+ * Shared event-shape constants for the TR-023 rename-cascade consumer.
99
+ * The cascade's input detail-type (on the data event bus) and its two
100
+ * terminal detail-types (on the ops event bus) are owned by
101
+ * `@openhi/workflows`; this module re-imports them so the workflow
102
+ * construct can wire the EventBridge rule and the terminal publisher
103
+ * from a single place.
104
+ *
105
+ * @see .state/adr-018-implementation-guide.md section 5
106
+ */
107
+
108
+ /**
109
+ * Stable logical name registered with the shared `WorkflowDedupTable`
110
+ * (TR-015). The state machine's `DedupCheck` state writes a row keyed
111
+ * by `(consumerName, eventId, attempt)` to absorb EventBridge retries.
112
+ */
113
+ declare const RENAME_CASCADE_CONSUMER_NAME: "rename-cascade";
114
+ /**
115
+ * Distributed-Map max concurrency. Per the ADR-018 implementation guide
116
+ * section 5: Distributed Map (NOT inline — TR-022 owning-delete uses
117
+ * inline), tunable via the construct's `cascadeMapConcurrency` prop.
118
+ * Operators may scale this down on first rollout.
119
+ */
120
+ declare const RENAME_CASCADE_DEFAULT_CONCURRENCY: 10;
121
+ /**
122
+ * `CascadeFailed` alarm threshold — fires when ExecutionsFailed exceeds
123
+ * the value over the configured period. Per the implementation guide
124
+ * section 5 "Alarm thresholds" table.
125
+ */
126
+ declare const RENAME_CASCADE_FAILED_THRESHOLD: 0;
127
+ /**
128
+ * `CascadeSlow` alarm threshold (in seconds) — fires when ExecutionTime
129
+ * p99 exceeds the value. Per the implementation guide section 5.
130
+ */
131
+ declare const RENAME_CASCADE_SLOW_THRESHOLD_SECONDS: 300;
132
+ /**
133
+ * Inputs the cascade list-targets step receives. Most fields come
134
+ * straight off the `ControlPlaneRenameV1` envelope payload; `cursors`
135
+ * threads through the outer loop.
136
+ */
137
+ interface RenameCascadeListInput {
138
+ readonly entityType: RenamableEntityType;
139
+ readonly entityId: string;
140
+ readonly tenantId?: string;
141
+ readonly oldName: string;
142
+ readonly newName: string;
143
+ readonly oldNormalizedName: string;
144
+ readonly newNormalizedName: string;
145
+ readonly cursors?: Record<string, string | null>;
146
+ /** Cumulative `itemsRewritten` carried forward across pages. */
147
+ readonly itemsRewritten?: number;
148
+ /** Cumulative `chunkCount` carried forward across pages. */
149
+ readonly chunkCount?: number;
150
+ }
151
+ /** Inputs the cascade rewrite-chunk step receives — one chunk per Map iteration. */
152
+ interface RenameCascadeChunkInput {
153
+ readonly entityType: RenamableEntityType;
154
+ readonly entityId: string;
155
+ readonly tenantId?: string;
156
+ /** Targets to rewrite in this transaction. Length must be 1..50. */
157
+ readonly targets: ReadonlyArray<RenameCascadeRewriteTarget>;
158
+ /**
159
+ * Idempotency token uniquely identifying this chunk within the
160
+ * cascade execution. Forwarded to `executeMultiWrite` so replayed
161
+ * chunks land idempotently.
162
+ */
163
+ readonly chunkToken: string;
164
+ }
165
+ /** Outputs the cascade list-targets step emits to feed the Distributed Map state. */
166
+ interface RenameCascadeListOutput {
167
+ readonly entityType: RenamableEntityType;
168
+ readonly entityId: string;
169
+ readonly tenantId?: string;
170
+ readonly oldName: string;
171
+ readonly newName: string;
172
+ readonly oldNormalizedName: string;
173
+ readonly newNormalizedName: string;
174
+ readonly cursors: Record<string, string | null>;
175
+ readonly chunks: ReadonlyArray<RenameCascadeChunkInput>;
176
+ readonly exhausted: boolean;
177
+ readonly itemsRewritten: number;
178
+ readonly chunkCount: number;
179
+ }
180
+ /** Inputs the cascade finalize step receives. */
181
+ interface RenameCascadeFinalizeInput {
182
+ readonly entityType: RenamableEntityType;
183
+ readonly entityId: string;
184
+ readonly tenantId?: string;
185
+ readonly newName: string;
186
+ readonly itemsRewritten: number;
187
+ readonly chunkCount: number;
188
+ readonly startedAt: string;
189
+ /** Optional eventId / correlation for ADR-016 envelope chaining. */
190
+ readonly eventId?: string;
191
+ readonly correlationId?: string;
192
+ readonly causationId?: string;
193
+ }
194
+ /** Outputs the cascade finalize step emits (used by tests + telemetry). */
195
+ interface RenameCascadeFinalizeOutput {
196
+ readonly entityType: RenamableEntityType;
197
+ readonly entityId: string;
198
+ readonly tenantId?: string;
199
+ readonly newName: string;
200
+ readonly itemsRewritten: number;
201
+ readonly chunkCount: number;
202
+ readonly durationMs: number;
203
+ readonly completedAt: string;
204
+ }
205
+ /** Env var the construct uses to inject the ops event bus name into the finalize Lambda. */
206
+ declare const RENAME_CASCADE_OPS_EVENT_BUS_ENV_VAR: "RENAME_CASCADE_OPS_EVENT_BUS_NAME";
207
+
208
+ export { RENAME_CASCADE_CONSUMER_NAME as R, RENAME_CASCADE_DEFAULT_CONCURRENCY as a, RENAME_CASCADE_FAILED_THRESHOLD as b, RENAME_CASCADE_OPS_EVENT_BUS_ENV_VAR as c, RENAME_CASCADE_SLOW_THRESHOLD_SECONDS as d, type RenameCascadeChunkInput as e, type RenameCascadeFinalizeInput as f, type RenameCascadeFinalizeOutput as g, type RenameCascadeListInput as h, type RenameCascadeListOutput as i };
@@ -0,0 +1,35 @@
1
+ import { EventBridgeClient } from '@aws-sdk/client-eventbridge';
2
+ import { a as CascadeFinalizeInput, b as CascadeFinalizeOutput } from './events-CjS-sm0W.mjs';
3
+ export { g as OWNING_DELETE_OPS_EVENT_BUS_ENV_VAR } from './events-CjS-sm0W.mjs';
4
+
5
+ /**
6
+ * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/owning-delete-cascade/finalize-handler.md
7
+ *
8
+ * Final step of the TR-022 hard-delete cascade.
9
+ *
10
+ * After the inline Map state drains every child projection from the
11
+ * owner's partition, this handler:
12
+ *
13
+ * 1. Deletes the owning canonical row at `SK = "CURRENT"` conditional
14
+ * on `lifecycleState = "deleting"`. Idempotent — a replayed
15
+ * finalize after a prior successful run returns `deleted: false`
16
+ * silently.
17
+ * 2. Emits `control-plane.owning-delete-complete.v1` on the ops event
18
+ * bus, carrying the cascade's chunk count, projections removed,
19
+ * and duration.
20
+ *
21
+ * The handler only emits the terminal event when the canonical
22
+ * delete actually succeeded on this call (`canonicalDeleted: true`).
23
+ * On replay where the canonical row is already gone, the handler
24
+ * returns without re-emitting — the original event already fired.
25
+ */
26
+
27
+ /** Test seam: per-handler-call EventBridge client + clock. */
28
+ interface FinalizeHandlerDependencies {
29
+ readonly eventBridgeClient?: EventBridgeClient;
30
+ readonly now?: () => Date;
31
+ readonly eventIdGenerator?: () => string;
32
+ }
33
+ declare const handler: (input: CascadeFinalizeInput, deps?: FinalizeHandlerDependencies) => Promise<CascadeFinalizeOutput>;
34
+
35
+ export { type FinalizeHandlerDependencies, handler };