@memberjunction/record-cloning-base 0.0.1-seed.1 → 6.2.0-edge.2

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 (59) hide show
  1. package/LICENSE +183 -0
  2. package/README.md +29 -3
  3. package/dist/CloneConfigValidator.d.ts +109 -0
  4. package/dist/CloneConfigValidator.d.ts.map +1 -0
  5. package/dist/CloneConfigValidator.js +348 -0
  6. package/dist/CloneConfigValidator.js.map +1 -0
  7. package/dist/CloneFieldMapper.d.ts +103 -0
  8. package/dist/CloneFieldMapper.d.ts.map +1 -0
  9. package/dist/CloneFieldMapper.js +369 -0
  10. package/dist/CloneFieldMapper.js.map +1 -0
  11. package/dist/ClonePlanHash.d.ts +27 -0
  12. package/dist/ClonePlanHash.d.ts.map +1 -0
  13. package/dist/ClonePlanHash.js +130 -0
  14. package/dist/ClonePlanHash.js.map +1 -0
  15. package/dist/ClonePolicyResolver.d.ts +100 -0
  16. package/dist/ClonePolicyResolver.d.ts.map +1 -0
  17. package/dist/ClonePolicyResolver.js +247 -0
  18. package/dist/ClonePolicyResolver.js.map +1 -0
  19. package/dist/EffectiveOptions.d.ts +78 -0
  20. package/dist/EffectiveOptions.d.ts.map +1 -0
  21. package/dist/EffectiveOptions.js +156 -0
  22. package/dist/EffectiveOptions.js.map +1 -0
  23. package/dist/ExclusionClasses.d.ts +27 -0
  24. package/dist/ExclusionClasses.d.ts.map +1 -0
  25. package/dist/ExclusionClasses.js +81 -0
  26. package/dist/ExclusionClasses.js.map +1 -0
  27. package/dist/FieldMeta.d.ts +15 -0
  28. package/dist/FieldMeta.d.ts.map +1 -0
  29. package/dist/FieldMeta.js +41 -0
  30. package/dist/FieldMeta.js.map +1 -0
  31. package/dist/JsonRemapEngine.d.ts +42 -0
  32. package/dist/JsonRemapEngine.d.ts.map +1 -0
  33. package/dist/JsonRemapEngine.js +251 -0
  34. package/dist/JsonRemapEngine.js.map +1 -0
  35. package/dist/NameTemplate.d.ts +56 -0
  36. package/dist/NameTemplate.d.ts.map +1 -0
  37. package/dist/NameTemplate.js +193 -0
  38. package/dist/NameTemplate.js.map +1 -0
  39. package/dist/RowExclusion.d.ts +9 -0
  40. package/dist/RowExclusion.d.ts.map +1 -0
  41. package/dist/RowExclusion.js +19 -0
  42. package/dist/RowExclusion.js.map +1 -0
  43. package/dist/SensitiveValues.d.ts +12 -0
  44. package/dist/SensitiveValues.d.ts.map +1 -0
  45. package/dist/SensitiveValues.js +25 -0
  46. package/dist/SensitiveValues.js.map +1 -0
  47. package/dist/UniqueKeyClassifier.d.ts +52 -0
  48. package/dist/UniqueKeyClassifier.d.ts.map +1 -0
  49. package/dist/UniqueKeyClassifier.js +161 -0
  50. package/dist/UniqueKeyClassifier.js.map +1 -0
  51. package/dist/index.d.ts +19 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +19 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/types.d.ts +260 -0
  56. package/dist/types.d.ts.map +1 -0
  57. package/dist/types.js +31 -0
  58. package/dist/types.js.map +1 -0
  59. package/package.json +28 -5
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClonePolicyResolver.d.ts","sourceRoot":"","sources":["../src/ClonePolicyResolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,247 @@
1
+ /**
2
+ * @file ClonePolicyResolver.ts
3
+ * 8-tier precedence hierarchy for clone edge policy resolution.
4
+ * Evaluates Built-in -> Constraint -> Child Entity -> Relationship -> Root Entity -> Preset -> Request.
5
+ * Enforces:
6
+ * - A child entity marked NotCloneable (or AllowCreateAPI=false) is skipped everywhere, unconditionally.
7
+ * - Name heuristics (runs, logs, per-user state) skip a child only when no configuration names that edge.
8
+ * - Unlisted relationships are Skip: each configuration opts in to what it copies. There are no
9
+ * entity-specific defaults.
10
+ * - A self-relationship is Deep only when its join column is a hierarchy (IsHierarchy) field.
11
+ * - A unique FK makes Reference impossible, so it turns Reference into Deep; it never overrides Skip.
12
+ * - Locked edges ignore preset and request overrides (LOCKED_EDGE_OVERRIDE_IGNORED).
13
+ * @see plans/record-cloning/README.md §4.4, §5.3–§5.5, §13.1
14
+ */
15
+ import { EvaluateExclusionClass } from './ExclusionClasses.js';
16
+ /**
17
+ * Resolves the edge traversal policy according to the 8-tier precedence hierarchy.
18
+ */
19
+ export function ResolveEdgePolicy(ctx) {
20
+ const warnings = [];
21
+ const configuredPolicy = ctx.RelationshipConfig?.Policy ??
22
+ rootRelationship(ctx)?.Policy ??
23
+ BagEntry(ctx.RootEntityConfig?.Descendants, ctx.ChildEntityName)?.Policy ??
24
+ parentRelationship(ctx)?.Policy;
25
+ // TIER 0 / EXCLUSION. Explicit NotCloneable and AllowCreateAPI=false win unconditionally.
26
+ // The name heuristics only apply when no configuration says what to do with this edge.
27
+ const exclusion = EvaluateExclusionClass({
28
+ EntityName: ctx.ChildEntityName,
29
+ NotCloneable: ctx.ChildEntityConfig?.NotCloneable,
30
+ NotCloneableReason: ctx.ChildEntityConfig?.NotCloneableReason,
31
+ AllowCreateAPI: ctx.ChildEntityConfig?.AllowCreateAPI,
32
+ HeuristicsOnly: false,
33
+ });
34
+ const heuristic = configuredPolicy
35
+ ? { Excluded: false }
36
+ : EvaluateExclusionClass({ EntityName: ctx.ChildEntityName, HeuristicsOnly: true });
37
+ for (const result of [exclusion, heuristic]) {
38
+ if (!result.Excluded)
39
+ continue;
40
+ // Say so only when something would otherwise copy these rows. Unlisted relationships are
41
+ // skipped anyway, and a note for each of them buries the warnings that matter.
42
+ return {
43
+ Policy: 'Skip',
44
+ PolicySource: 'Entity',
45
+ Locked: true,
46
+ Warnings: wouldCopy(ctx, configuredPolicy)
47
+ ? [
48
+ {
49
+ Code: 'NOT_CLONEABLE',
50
+ Severity: 'Warning',
51
+ NodeKey: ctx.ToKey,
52
+ Message: result.Reason || `Child entity '${ctx.ChildEntityName}' is excluded or NotCloneable.`,
53
+ },
54
+ ]
55
+ : [],
56
+ };
57
+ }
58
+ // 1. Engine Built-in Default
59
+ let policy = 'Skip';
60
+ let policySource = 'BuiltIn';
61
+ let locked = false;
62
+ switch (ctx.Kind) {
63
+ case 'IsASubtype':
64
+ case 'Embedded':
65
+ case 'Collection':
66
+ policy = 'Deep';
67
+ break;
68
+ case 'Relationship':
69
+ // Unlisted one-to-many relationships are not followed: CodeGen creates one for every FK,
70
+ // so following them by default copies (and grafts rows onto) records the clone doesn't own.
71
+ policy = 'Skip';
72
+ break;
73
+ case 'ForwardFK':
74
+ case 'SelfPointer':
75
+ policy = 'Reference';
76
+ break;
77
+ case 'InboundFK':
78
+ case 'SoftLink':
79
+ policy = 'Skip';
80
+ break;
81
+ case 'Hierarchy':
82
+ // A self-relationship is a tree only when its join column is flagged IsHierarchy.
83
+ policy = ctx.IsHierarchyField ? 'Deep' : 'Skip';
84
+ break;
85
+ default:
86
+ policy = 'Skip';
87
+ break;
88
+ }
89
+ // 2. Constraint-derived decisions are applied at the end: a unique FK only rules out Reference.
90
+ // 3. Child Entity Bag (already handled NotCloneable above)
91
+ // 4. Relationship Bag (IEntityRelationshipConfiguration.Clone)
92
+ if (ctx.RelationshipConfig) {
93
+ if (ctx.RelationshipConfig.Locked) {
94
+ locked = true;
95
+ }
96
+ if (ctx.RelationshipConfig.Policy) {
97
+ policy = ctx.RelationshipConfig.Policy;
98
+ policySource = 'Relationship';
99
+ }
100
+ }
101
+ // 4b. The parent entity's own configuration, below the root
102
+ const parentMatch = parentRelationship(ctx);
103
+ if (parentMatch) {
104
+ if (parentMatch.Locked)
105
+ locked = true;
106
+ if (parentMatch.Policy) {
107
+ policy = parentMatch.Policy;
108
+ policySource = 'Entity';
109
+ }
110
+ }
111
+ // 5. Root Entity Bag (Relationships & Descendants)
112
+ if (ctx.RootEntityConfig) {
113
+ const relMatch = rootRelationship(ctx);
114
+ if (relMatch) {
115
+ if (relMatch.Locked)
116
+ locked = true;
117
+ if (relMatch.Policy) {
118
+ policy = relMatch.Policy;
119
+ policySource = 'Descendant';
120
+ }
121
+ }
122
+ const descMatch = BagEntry(ctx.RootEntityConfig.Descendants, ctx.ChildEntityName);
123
+ if (descMatch) {
124
+ if (descMatch.Locked)
125
+ locked = true;
126
+ if (descMatch.Policy) {
127
+ policy = descMatch.Policy;
128
+ policySource = 'Descendant';
129
+ }
130
+ }
131
+ }
132
+ // 6. Preset (a Locked edge keeps its configured policy)
133
+ if (ctx.PresetConfig?.EdgeOverrides) {
134
+ const presetOverride = ctx.PresetConfig.EdgeOverrides.find((o) => (ctx.RelationshipID && o.RelationshipID === ctx.RelationshipID) ||
135
+ (o.ChildEntityName && o.ChildEntityName === ctx.ChildEntityName));
136
+ if (presetOverride && locked) {
137
+ warnings.push({
138
+ Code: 'LOCKED_EDGE_OVERRIDE_IGNORED',
139
+ Severity: 'Warning',
140
+ NodeKey: ctx.ToKey,
141
+ Message: `Preset policy '${presetOverride.Policy}' for edge to '${ctx.ChildEntityName}' was ignored because the edge is locked.`,
142
+ });
143
+ }
144
+ else if (presetOverride) {
145
+ policy = presetOverride.Policy;
146
+ policySource = 'Descendant';
147
+ }
148
+ }
149
+ // 7. Request Overrides
150
+ if (ctx.RequestOverrides && ctx.RequestOverrides.length > 0) {
151
+ const reqOverride = ctx.RequestOverrides.find((o) => {
152
+ if (o.RelationshipID && ctx.RelationshipID && o.RelationshipID === ctx.RelationshipID) {
153
+ return true;
154
+ }
155
+ if (o.FromKey && o.ToKey && o.FromKey === ctx.FromKey && o.ToKey === ctx.ToKey) {
156
+ return true;
157
+ }
158
+ return false;
159
+ });
160
+ if (reqOverride) {
161
+ if (locked) {
162
+ // Locked edge: user override is ignored with warning
163
+ warnings.push({
164
+ Code: 'LOCKED_EDGE_OVERRIDE_IGNORED',
165
+ Severity: 'Warning',
166
+ NodeKey: ctx.ToKey,
167
+ Message: `Override to '${reqOverride.Policy}' for edge to '${ctx.ChildEntityName}' was ignored because the edge is locked.`,
168
+ });
169
+ }
170
+ else {
171
+ policy = reqOverride.Policy;
172
+ policySource = 'Request';
173
+ }
174
+ }
175
+ }
176
+ // Unique FK: the child row can belong to one parent only, so pointing the copy at the same
177
+ // child (Reference) is impossible. Deep is the only way to follow it; Skip is always safe.
178
+ if (ctx.IsUniqueFK && policy === 'Reference') {
179
+ policy = 'Deep';
180
+ policySource = 'Constraint';
181
+ warnings.push({
182
+ Code: 'CONSTRAINT_FORCED_DEEP',
183
+ Severity: 'Warning',
184
+ NodeKey: ctx.ToKey,
185
+ Message: `Unique FK constraint on '${ctx.JoinField}' makes Reference impossible; the child is copied instead.`,
186
+ });
187
+ }
188
+ return {
189
+ Policy: policy,
190
+ PolicySource: policySource,
191
+ Locked: locked,
192
+ Warnings: warnings,
193
+ };
194
+ }
195
+ /**
196
+ * The root's entry for this edge: by relationship ID or "<Child>.<JoinField>" at any depth, by bare
197
+ * child name only on edges from the root's entity. A child can hang from several entities in the walk
198
+ * (AI Agent Actions from the agent by AgentID and from a copied prompt by CompactPromptID); a bare key
199
+ * written for the root's own rows must not copy another record's rows that point at a copied one.
200
+ */
201
+ function rootRelationship(ctx) {
202
+ const rels = ctx.RootEntityConfig?.Relationships;
203
+ if (!rels)
204
+ return undefined;
205
+ return ((ctx.RelationshipID ? BagEntry(rels, ctx.RelationshipID) : undefined) ??
206
+ BagEntry(rels, `${ctx.ChildEntityName}.${ctx.JoinField}`) ??
207
+ (IsEdgeFromRoot(ctx.ParentEntityName, ctx.RootEntityName) ? BagEntry(rels, ctx.ChildEntityName) : undefined));
208
+ }
209
+ /** Whether an edge from `parentEntityName` starts at the root's entity (ignoring case); true when the root isn't given. */
210
+ export function IsEdgeFromRoot(parentEntityName, rootEntityName) {
211
+ return !rootEntityName || parentEntityName.toLowerCase() === rootEntityName.toLowerCase();
212
+ }
213
+ /** The parent entity's own entry for this edge: by relationship ID, "<Child>.<JoinField>", or child name. */
214
+ function parentRelationship(ctx) {
215
+ const rels = ctx.ParentEntityConfig?.Relationships;
216
+ if (!rels)
217
+ return undefined;
218
+ return (ctx.RelationshipID ? BagEntry(rels, ctx.RelationshipID) : undefined) ?? BagEntry(rels, `${ctx.ChildEntityName}.${ctx.JoinField}`) ?? BagEntry(rels, ctx.ChildEntityName);
219
+ }
220
+ /**
221
+ * An entry of a `Relationships` or `Descendants` bag by key, ignoring case, as the validator
222
+ * matches keys: a miscased column (`AgentId` for `AgentID`) must not validate clean and then
223
+ * silently fall back to the default policy.
224
+ */
225
+ export function BagEntry(bag, key) {
226
+ if (!bag || !key)
227
+ return undefined;
228
+ if (key in bag)
229
+ return bag[key];
230
+ const target = key.toLowerCase();
231
+ const found = Object.keys(bag).find((k) => k.toLowerCase() === target);
232
+ return found === undefined ? undefined : bag[found];
233
+ }
234
+ /** Whether anything asks for this edge to be copied: configuration, the edge kind's default, a preset or the request. */
235
+ function wouldCopy(ctx, configuredPolicy) {
236
+ if (configuredPolicy === 'Deep')
237
+ return true;
238
+ if (configuredPolicy === undefined) {
239
+ const deepByDefault = ctx.Kind === 'IsASubtype' || ctx.Kind === 'Embedded' || ctx.Kind === 'Collection' || (ctx.Kind === 'Hierarchy' && ctx.IsHierarchyField === true);
240
+ if (deepByDefault)
241
+ return true;
242
+ }
243
+ const preset = ctx.PresetConfig?.EdgeOverrides?.some((o) => o.Policy === 'Deep' && ((ctx.RelationshipID && o.RelationshipID === ctx.RelationshipID) || o.ChildEntityName === ctx.ChildEntityName));
244
+ const request = ctx.RequestOverrides?.some((o) => o.Policy === 'Deep' && ((o.RelationshipID && o.RelationshipID === ctx.RelationshipID) || (o.FromKey === ctx.FromKey && o.ToKey === ctx.ToKey)));
245
+ return !!preset || !!request;
246
+ }
247
+ //# sourceMappingURL=ClonePolicyResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClonePolicyResolver.js","sourceRoot":"","sources":["../src/ClonePolicyResolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @file EffectiveOptions.ts
3
+ * Resolves the options a clone plan actually runs with from the root entity's clone
4
+ * configuration and the caller's request.
5
+ *
6
+ * - The entity's `Configuration.Clone` supplies every default.
7
+ * - **Narrowing** scope (lower caps; excluding subtypes, soft links or the hierarchy subtree) is
8
+ * allowed when `UserEditable` is `'scope'` or `'all'` (the default), or for an override holder.
9
+ * - **Widening** scope (higher caps; including what the configuration leaves out) needs the
10
+ * `Clone Records: Override Scope` authorization, whatever `UserEditable` says.
11
+ * - Entity Actions fire by default and AI Actions are suppressed; the configuration's `Hooks`
12
+ * changes either. Changing that from a request, in either direction, needs
13
+ * `Clone Records: Fire Hooks`: suppressing automations is as consequential as firing them.
14
+ *
15
+ * Every ignored request value produces a warning, so the review shows what was not applied.
16
+ *
17
+ * @see plans/record-cloning/README.md §4.1, §9.4
18
+ */
19
+ import type { CloneRequestOptions, ClonePlan, CloneWarning } from './types.js';
20
+ /** The subset of `IEntityCloneConfiguration` this resolver reads. */
21
+ export interface EffectiveOptionsConfig {
22
+ MaxDepth?: number;
23
+ MaxRecords?: number;
24
+ Subtypes?: 'include' | 'exclude';
25
+ Hierarchy?: 'subtree' | 'node';
26
+ SoftLinks?: 'skip' | 'include';
27
+ Embeddings?: 'copy' | 'regenerate';
28
+ UserEditable?: 'none' | 'fields' | 'scope' | 'all';
29
+ Hooks?: {
30
+ EntityActions?: 'suppress' | 'fire';
31
+ AIActions?: 'suppress' | 'fire';
32
+ };
33
+ }
34
+ export type EffectiveCloneOptions = ClonePlan['EffectiveOptions'];
35
+ /** What the caller is authorized to do beyond the entity's configuration. */
36
+ export interface CloneOptionGrants {
37
+ /** Holds `Clone Records: Fire Hooks`: may change whether Entity Actions / AI Actions run. */
38
+ CanFireHooks: boolean;
39
+ /** Holds `Clone Records: Override Scope`. */
40
+ CanOverrideScope: boolean;
41
+ }
42
+ /** Built-in defaults when neither the entity nor the request says otherwise. */
43
+ export declare const DEFAULT_CLONE_MAX_DEPTH = 3;
44
+ export declare const DEFAULT_CLONE_MAX_RECORDS = 500;
45
+ /** Entity Actions on the cloned rows run, as they would for any create. */
46
+ export declare const DEFAULT_CLONE_ENTITY_ACTIONS: 'suppress' | 'fire';
47
+ /** AI Actions stay off unless configured: each can be a paid model call per cloned row. */
48
+ export declare const DEFAULT_CLONE_AI_ACTIONS: 'suppress' | 'fire';
49
+ export interface EffectiveOptionsResult {
50
+ Options: EffectiveCloneOptions;
51
+ Warnings: CloneWarning[];
52
+ /** Options changed beyond the configuration under an authorization (Override Scope, Fire Hooks); recorded on the clone log. */
53
+ Overrides: string[];
54
+ }
55
+ /**
56
+ * Merges the request's options onto the entity's configured defaults under the rules above.
57
+ * @param config The root entity's clone configuration, or null when it has none.
58
+ * @param request The options the caller sent.
59
+ * @param grants What the caller is authorized to do beyond the configuration.
60
+ */
61
+ export declare function ResolveEffectiveCloneOptions(config: EffectiveOptionsConfig | null | undefined, request: CloneRequestOptions | null | undefined, grants: CloneOptionGrants): EffectiveOptionsResult;
62
+ /** A preset in the documented `Clone.Presets` array shape. */
63
+ export interface NormalizedClonePreset {
64
+ Key: string;
65
+ Label: string;
66
+ Description?: string;
67
+ Options?: CloneRequestOptions;
68
+ Relationships?: Record<string, {
69
+ Policy: 'Deep' | 'Reference' | 'Skip';
70
+ }>;
71
+ }
72
+ /**
73
+ * Reads `Clone.Presets` defensively. The documented shape is an array of `{ Key, Label, ... }`;
74
+ * the legacy keyed-object form (`{ "<key>": { Description, Relationships } }`) is still accepted,
75
+ * with the object key as `Key`. Anything else yields no presets rather than an exception.
76
+ */
77
+ export declare function NormalizeClonePresets(presets: unknown): NormalizedClonePreset[];
78
+ //# sourceMappingURL=EffectiveOptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EffectiveOptions.d.ts","sourceRoot":"","sources":["../src/EffectiveOptions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5E,qEAAqE;AACrE,MAAM,WAAW,sBAAsB;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACjC,SAAS,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAC;IACnD,KAAK,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;KAAE,CAAC;CACpF;AAED,MAAM,MAAM,qBAAqB,GAAG,SAAS,CAAC,kBAAkB,CAAC,CAAC;AAElE,6EAA6E;AAC7E,MAAM,WAAW,iBAAiB;IAC9B,6FAA6F;IAC7F,YAAY,EAAE,OAAO,CAAC;IACtB,6CAA6C;IAC7C,gBAAgB,EAAE,OAAO,CAAC;CAC7B;AAED,gFAAgF;AAChF,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,2EAA2E;AAC3E,eAAO,MAAM,4BAA4B,EAAE,UAAU,GAAG,MAAe,CAAC;AACxE,2FAA2F;AAC3F,eAAO,MAAM,wBAAwB,EAAE,UAAU,GAAG,MAAmB,CAAC;AAExE,MAAM,WAAW,sBAAsB;IACnC,OAAO,EAAE,qBAAqB,CAAC;IAC/B,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,+HAA+H;IAC/H,SAAS,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CACxC,MAAM,EAAE,sBAAsB,GAAG,IAAI,GAAG,SAAS,EACjD,OAAO,EAAE,mBAAmB,GAAG,IAAI,GAAG,SAAS,EAC/C,MAAM,EAAE,iBAAiB,GAC1B,sBAAsB,CA0FxB;AAED,8DAA8D;AAC9D,MAAM,WAAW,qBAAqB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7E;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,qBAAqB,EAAE,CAyB/E"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * @file EffectiveOptions.ts
3
+ * Resolves the options a clone plan actually runs with from the root entity's clone
4
+ * configuration and the caller's request.
5
+ *
6
+ * - The entity's `Configuration.Clone` supplies every default.
7
+ * - **Narrowing** scope (lower caps; excluding subtypes, soft links or the hierarchy subtree) is
8
+ * allowed when `UserEditable` is `'scope'` or `'all'` (the default), or for an override holder.
9
+ * - **Widening** scope (higher caps; including what the configuration leaves out) needs the
10
+ * `Clone Records: Override Scope` authorization, whatever `UserEditable` says.
11
+ * - Entity Actions fire by default and AI Actions are suppressed; the configuration's `Hooks`
12
+ * changes either. Changing that from a request, in either direction, needs
13
+ * `Clone Records: Fire Hooks`: suppressing automations is as consequential as firing them.
14
+ *
15
+ * Every ignored request value produces a warning, so the review shows what was not applied.
16
+ *
17
+ * @see plans/record-cloning/README.md §4.1, §9.4
18
+ */
19
+ /** Built-in defaults when neither the entity nor the request says otherwise. */
20
+ export const DEFAULT_CLONE_MAX_DEPTH = 3;
21
+ export const DEFAULT_CLONE_MAX_RECORDS = 500;
22
+ /** Entity Actions on the cloned rows run, as they would for any create. */
23
+ export const DEFAULT_CLONE_ENTITY_ACTIONS = 'fire';
24
+ /** AI Actions stay off unless configured: each can be a paid model call per cloned row. */
25
+ export const DEFAULT_CLONE_AI_ACTIONS = 'suppress';
26
+ /**
27
+ * Merges the request's options onto the entity's configured defaults under the rules above.
28
+ * @param config The root entity's clone configuration, or null when it has none.
29
+ * @param request The options the caller sent.
30
+ * @param grants What the caller is authorized to do beyond the configuration.
31
+ */
32
+ export function ResolveEffectiveCloneOptions(config, request, grants) {
33
+ const warnings = [];
34
+ const overrides = [];
35
+ const editable = config?.UserEditable ?? 'all';
36
+ const mayNarrow = editable === 'scope' || editable === 'all' || grants.CanOverrideScope;
37
+ const narrowIgnored = (option, value) => {
38
+ warnings.push({
39
+ Code: 'OPTION_OVERRIDE_IGNORED',
40
+ Severity: 'Warning',
41
+ Field: option,
42
+ Message: `${option} = ${String(value)} was ignored: this entity's clone configuration sets UserEditable to '${editable}'.`,
43
+ });
44
+ };
45
+ const widenIgnored = (option, value, configured) => {
46
+ warnings.push({
47
+ Code: 'SCOPE_OVERRIDE_FORBIDDEN',
48
+ Severity: 'Warning',
49
+ Field: option,
50
+ Message: `${option} = ${String(value)} was ignored: going beyond the configured ${String(configured)} needs the 'Clone Records: Override Scope' authorization.`,
51
+ });
52
+ };
53
+ /** A two-valued scope switch where `wide` copies more than the other value. */
54
+ const scope = (option, requested, configured, wide) => {
55
+ if (requested === undefined || requested === configured)
56
+ return configured;
57
+ if (requested === wide) {
58
+ if (grants.CanOverrideScope) {
59
+ overrides.push(option);
60
+ return requested;
61
+ }
62
+ widenIgnored(option, requested, configured);
63
+ return configured;
64
+ }
65
+ if (mayNarrow)
66
+ return requested;
67
+ narrowIgnored(option, requested);
68
+ return configured;
69
+ };
70
+ const cap = (option, requested, configured) => {
71
+ if (requested === undefined || !Number.isFinite(requested) || Math.floor(requested) === configured)
72
+ return configured;
73
+ const value = Math.max(1, Math.floor(requested));
74
+ if (value > configured) {
75
+ if (grants.CanOverrideScope) {
76
+ overrides.push(option);
77
+ return value;
78
+ }
79
+ widenIgnored(option, requested, configured);
80
+ return configured;
81
+ }
82
+ if (mayNarrow)
83
+ return value;
84
+ narrowIgnored(option, requested);
85
+ return configured;
86
+ };
87
+ /** A choice that is neither wider nor narrower, governed by UserEditable alone. */
88
+ const choice = (option, requested, configured) => {
89
+ if (requested === undefined || requested === configured)
90
+ return configured;
91
+ if (mayNarrow)
92
+ return requested;
93
+ narrowIgnored(option, requested);
94
+ return configured;
95
+ };
96
+ const hook = (option, requested, configured) => {
97
+ if (requested === undefined || requested === configured)
98
+ return configured;
99
+ if (grants.CanFireHooks) {
100
+ overrides.push(option);
101
+ return requested;
102
+ }
103
+ warnings.push({
104
+ Code: 'HOOKS_FORBIDDEN',
105
+ Severity: 'Warning',
106
+ Field: option,
107
+ Message: `${option} = ${requested} was ignored: changing whether they run needs the 'Clone Records: Fire Hooks' authorization. They ${configured === 'fire' ? 'run' : 'stay suppressed'} as configured.`,
108
+ });
109
+ return configured;
110
+ };
111
+ const options = {
112
+ MaxDepth: cap('MaxDepth', request?.MaxDepth, config?.MaxDepth ?? DEFAULT_CLONE_MAX_DEPTH),
113
+ MaxRecords: cap('MaxRecords', request?.MaxRecords, config?.MaxRecords ?? DEFAULT_CLONE_MAX_RECORDS),
114
+ Subtypes: scope('Subtypes', request?.Subtypes, config?.Subtypes ?? 'include', 'include'),
115
+ Hierarchy: scope('Hierarchy', request?.Hierarchy, config?.Hierarchy ?? 'subtree', 'subtree'),
116
+ SoftLinks: scope('SoftLinks', request?.SoftLinks, config?.SoftLinks ?? 'skip', 'include'),
117
+ Embeddings: choice('Embeddings', request?.Embeddings, config?.Embeddings ?? 'copy'),
118
+ EntityActions: hook('EntityActions', request?.EntityActions, config?.Hooks?.EntityActions ?? DEFAULT_CLONE_ENTITY_ACTIONS),
119
+ AIActions: hook('AIActions', request?.AIActions, config?.Hooks?.AIActions ?? DEFAULT_CLONE_AI_ACTIONS),
120
+ };
121
+ return { Options: options, Warnings: warnings, Overrides: overrides };
122
+ }
123
+ /**
124
+ * Reads `Clone.Presets` defensively. The documented shape is an array of `{ Key, Label, ... }`;
125
+ * the legacy keyed-object form (`{ "<key>": { Description, Relationships } }`) is still accepted,
126
+ * with the object key as `Key`. Anything else yields no presets rather than an exception.
127
+ */
128
+ export function NormalizeClonePresets(presets) {
129
+ const toPreset = (raw, fallbackKey) => {
130
+ if (!raw || typeof raw !== 'object')
131
+ return null;
132
+ const p = raw;
133
+ const key = typeof p.Key === 'string' && p.Key ? p.Key : typeof p.Name === 'string' && p.Name ? p.Name : fallbackKey;
134
+ if (!key)
135
+ return null;
136
+ return {
137
+ Key: key,
138
+ Label: typeof p.Label === 'string' && p.Label ? p.Label : key,
139
+ Description: typeof p.Description === 'string' ? p.Description : undefined,
140
+ Options: p.Options && typeof p.Options === 'object' ? p.Options : undefined,
141
+ Relationships: p.Relationships && typeof p.Relationships === 'object'
142
+ ? p.Relationships
143
+ : undefined,
144
+ };
145
+ };
146
+ if (Array.isArray(presets)) {
147
+ return presets.map((p) => toPreset(p)).filter((p) => p !== null);
148
+ }
149
+ if (presets && typeof presets === 'object') {
150
+ return Object.entries(presets)
151
+ .map(([key, p]) => toPreset(p, key))
152
+ .filter((p) => p !== null);
153
+ }
154
+ return [];
155
+ }
156
+ //# sourceMappingURL=EffectiveOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EffectiveOptions.js","sourceRoot":"","sources":["../src/EffectiveOptions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @file ExclusionClasses.ts
3
+ * Classification and detection of non-cloneable and transient entity classes.
4
+ * @see plans/record-cloning/README.md §5.3
5
+ */
6
+ export type ExclusionCategory = 'RunLogAudit' | 'PublishArtifactOrVersion' | 'ComputedOutput' | 'LiveCredentialsOrExternalHandle' | 'PersonalOrRespondentData' | 'PerUserState' | 'CreateDisallowed' | 'SoftDeleted';
7
+ export interface ExclusionEvaluation {
8
+ Excluded: boolean;
9
+ Category?: ExclusionCategory;
10
+ Reason?: string;
11
+ }
12
+ /**
13
+ * Checks whether an entity belongs to an exclusion class based on its configuration,
14
+ * metadata flags, and naming patterns.
15
+ */
16
+ export declare function EvaluateExclusionClass(params: {
17
+ EntityName: string;
18
+ NotCloneable?: boolean;
19
+ NotCloneableReason?: string;
20
+ AllowCreateAPI?: boolean;
21
+ /**
22
+ * true: evaluate only the name heuristics; false: only the explicit NotCloneable / AllowCreateAPI
23
+ * rules; omitted: both. Callers skip the heuristics when a configuration names the edge.
24
+ */
25
+ HeuristicsOnly?: boolean;
26
+ }): ExclusionEvaluation;
27
+ //# sourceMappingURL=ExclusionClasses.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExclusionClasses.d.ts","sourceRoot":"","sources":["../src/ExclusionClasses.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,iBAAiB,GACvB,aAAa,GACb,0BAA0B,GAC1B,gBAAgB,GAChB,iCAAiC,GACjC,0BAA0B,GAC1B,cAAc,GACd,kBAAkB,GAClB,aAAa,CAAC;AAEpB,MAAM,WAAW,mBAAmB;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AA6BD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG,mBAAmB,CAmDtB"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @file ExclusionClasses.ts
3
+ * Classification and detection of non-cloneable and transient entity classes.
4
+ * @see plans/record-cloning/README.md §5.3
5
+ */
6
+ /**
7
+ * Known heuristic patterns matching operational runs, audit logs, caches, etc.
8
+ */
9
+ const RUN_LOG_AUDIT_PATTERNS = [
10
+ /\bRuns?\b/i,
11
+ /\bRun Details?\b/i,
12
+ /\bRun Steps?\b/i,
13
+ /\bLogs?\b/i,
14
+ /\bChanges?\b/i,
15
+ /\bCache\b/i,
16
+ /\bWatermarks?\b/i,
17
+ /\bHistories\b/i,
18
+ /\bHistory\b/i,
19
+ /\bAudit\b/i,
20
+ /\bSnapshots?\b/i,
21
+ ];
22
+ /**
23
+ * Known heuristic patterns matching per-user runtime state.
24
+ */
25
+ const PER_USER_STATE_PATTERNS = [
26
+ /\bUser States?\b/i,
27
+ /\bUser Preferences?\b/i,
28
+ /\bFavorites?\b/i,
29
+ /\bNotifications?\b/i,
30
+ ];
31
+ /**
32
+ * Checks whether an entity belongs to an exclusion class based on its configuration,
33
+ * metadata flags, and naming patterns.
34
+ */
35
+ export function EvaluateExclusionClass(params) {
36
+ const { EntityName, NotCloneable, NotCloneableReason, AllowCreateAPI, HeuristicsOnly } = params;
37
+ const explicit = HeuristicsOnly !== true;
38
+ const heuristics = HeuristicsOnly !== false;
39
+ // 1. Explicit NotCloneable configuration
40
+ if (explicit && NotCloneable) {
41
+ return {
42
+ Excluded: true,
43
+ Category: 'RunLogAudit',
44
+ Reason: NotCloneableReason ||
45
+ `Entity '${EntityName}' is explicitly configured as NotCloneable.`,
46
+ };
47
+ }
48
+ // 2. AllowCreateAPI false: can never be created
49
+ if (explicit && AllowCreateAPI === false) {
50
+ return {
51
+ Excluded: true,
52
+ Category: 'CreateDisallowed',
53
+ Reason: `Entity '${EntityName}' has AllowCreateAPI=false in metadata and cannot be created.`,
54
+ };
55
+ }
56
+ if (!heuristics)
57
+ return { Excluded: false };
58
+ // 3. Heuristic: Run / Log / Audit / History patterns
59
+ for (const pattern of RUN_LOG_AUDIT_PATTERNS) {
60
+ if (pattern.test(EntityName)) {
61
+ return {
62
+ Excluded: true,
63
+ Category: 'RunLogAudit',
64
+ Reason: `Entity '${EntityName}' matches operational log, run, or history pattern.`,
65
+ };
66
+ }
67
+ }
68
+ // 4. Heuristic: per-user runtime state. A configuration that names the edge (checked by the
69
+ // caller) is the only way to copy it; there is no entity-specific exception.
70
+ for (const pattern of PER_USER_STATE_PATTERNS) {
71
+ if (pattern.test(EntityName)) {
72
+ return {
73
+ Excluded: true,
74
+ Category: 'PerUserState',
75
+ Reason: `Entity '${EntityName}' represents transient per-user state.`,
76
+ };
77
+ }
78
+ }
79
+ return { Excluded: false };
80
+ }
81
+ //# sourceMappingURL=ExclusionClasses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExclusionClasses.js","sourceRoot":"","sources":["../src/ExclusionClasses.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkBH;;GAEG;AACH,MAAM,sBAAsB,GAAG;IAC3B,YAAY;IACZ,mBAAmB;IACnB,iBAAiB;IACjB,YAAY;IACZ,eAAe;IACf,YAAY;IACZ,kBAAkB;IAClB,gBAAgB;IAChB,cAAc;IACd,YAAY;IACZ,iBAAiB;CACpB,CAAC;AAEF;;GAEG;AACH,MAAM,uBAAuB,GAAG;IAC5B,mBAAmB;IACnB,wBAAwB;IACxB,iBAAiB;IACjB,qBAAqB;CACxB,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAUtC;IACG,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,cAAc,EAAE,GAAG,MAAM,CAAC;IAChG,MAAM,QAAQ,GAAG,cAAc,KAAK,IAAI,CAAC;IACzC,MAAM,UAAU,GAAG,cAAc,KAAK,KAAK,CAAC;IAE5C,yCAAyC;IACzC,IAAI,QAAQ,IAAI,YAAY,EAAE,CAAC;QAC3B,OAAO;YACH,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,aAAa;YACvB,MAAM,EACF,kBAAkB;gBAClB,WAAW,UAAU,6CAA6C;SACzE,CAAC;IACN,CAAC;IAED,gDAAgD;IAChD,IAAI,QAAQ,IAAI,cAAc,KAAK,KAAK,EAAE,CAAC;QACvC,OAAO;YACH,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,kBAAkB;YAC5B,MAAM,EAAE,WAAW,UAAU,+DAA+D;SAC/F,CAAC;IACN,CAAC;IAED,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAE5C,qDAAqD;IACrD,KAAK,MAAM,OAAO,IAAI,sBAAsB,EAAE,CAAC;QAC3C,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,OAAO;gBACH,QAAQ,EAAE,IAAI;gBACd,QAAQ,EAAE,aAAa;gBACvB,MAAM,EAAE,WAAW,UAAU,qDAAqD;aACrF,CAAC;QACN,CAAC;IACL,CAAC;IAED,4FAA4F;IAC5F,gFAAgF;IAChF,KAAK,MAAM,OAAO,IAAI,uBAAuB,EAAE,CAAC;QAC5C,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,OAAO;gBACH,QAAQ,EAAE,IAAI;gBACd,QAAQ,EAAE,cAAc;gBACxB,MAAM,EAAE,WAAW,UAAU,wCAAwC;aACxE,CAAC;QACN,CAAC;IACL,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC/B,CAAC"}