filegrc 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/workflow.js CHANGED
@@ -107,7 +107,7 @@ async function assessWorkflowUnmeasured(input, options = {}) {
107
107
  generatedAt: evaluatedAt,
108
108
  programId: programRecord.type === "program" ? programRecord.id : undefined
109
109
  });
110
- const auditPreparations = options.auditPreparations || Object.fromEntries(await Promise.all(
110
+ const suppliedAuditPreparations = options.auditPreparations || Object.fromEntries(await Promise.all(
111
111
  audits.map(async (audit) => [
112
112
  audit.id,
113
113
  await assessAuditPreparation(loaded, {
@@ -117,7 +117,12 @@ async function assessWorkflowUnmeasured(input, options = {}) {
117
117
  })
118
118
  ])
119
119
  ));
120
+ const auditIds = new Set(audits.map(({ id }) => id));
121
+ const auditPreparations = Object.fromEntries(
122
+ Object.entries(suppliedAuditPreparations).filter(([id]) => auditIds.has(id))
123
+ );
120
124
  const obligationPlan = options.obligations || planObligations(loaded.resources, {
125
+ programId: programRecord.id,
121
126
  asOf,
122
127
  through: options.through || asOf,
123
128
  now: evaluatedAt,
@@ -154,7 +159,8 @@ async function assessWorkflowUnmeasured(input, options = {}) {
154
159
  ];
155
160
  const workItems = buildWorkItems(loaded.resources, obligationPlan, {
156
161
  asOf,
157
- includeComplete: Boolean(options.includeComplete)
162
+ includeComplete: Boolean(options.includeComplete),
163
+ programId: programRecord.id
158
164
  });
159
165
  const git = options.git || safeGitSummary(loaded.root);
160
166
  const assessments = buildAssessments({
@@ -818,6 +824,7 @@ async function assessPeriodHealth(loaded, options) {
818
824
  || record.controlIds.some((id) => selectedControlIds.has(id))
819
825
  ));
820
826
  const occurrences = planObligations(periodResources, {
827
+ programId: options.programId,
821
828
  from: coverage.start,
822
829
  asOf: periodThrough,
823
830
  through: periodThrough,
@@ -1137,7 +1144,7 @@ function findingSeverity(state, assessment) {
1137
1144
 
1138
1145
  function buildWorkItems(records, obligationPlan, options) {
1139
1146
  const byId = new Map(records.map((record) => [record.id, record]));
1140
- const items = obligationPlan.items.map((item) => obligationWorkItem(item, byId, options.asOf));
1147
+ const items = obligationPlan.items.map((item) => obligationWorkItem(item, byId, options.asOf, options.programId));
1141
1148
  const obligationSources = new Set(items
1142
1149
  .map((item) => item.source?.id)
1143
1150
  .filter(Boolean));
@@ -1171,7 +1178,7 @@ function buildWorkItems(records, obligationPlan, options) {
1171
1178
  return uniqueByKey(items);
1172
1179
  }
1173
1180
 
1174
- function obligationWorkItem(item, byId, asOf) {
1181
+ function obligationWorkItem(item, byId, asOf, programId) {
1175
1182
  const subjectId = item.subjectResourceId
1176
1183
  || (item.scopeResourceIds?.length === 1 ? item.scopeResourceIds[0] : null);
1177
1184
  const subjectRecord = subjectId ? byId.get(subjectId) : null;
@@ -1180,8 +1187,8 @@ function obligationWorkItem(item, byId, asOf) {
1180
1187
  key: `obligation:${item.key || item.actionItemId || item.obligationId}${subjectId ? `:${subjectId}` : ""}`,
1181
1188
  kind: item.kind === "calendar" ? "obligation-occurrence" : "assigned-work",
1182
1189
  source: {
1183
- type: item.actionItemId ? "action-item" : "obligation",
1184
- id: item.actionItemId || item.obligationId
1190
+ type: item.actionItemId ? "action-item" : item.occurrenceId ? "obligation-occurrence" : "obligation",
1191
+ id: item.actionItemId || item.occurrenceId || item.obligationId
1185
1192
  },
1186
1193
  ...(subjectId ? { subject: { type: subjectRecord?.type || "unknown", id: subjectId } } : {}),
1187
1194
  title: item.title,
@@ -1199,11 +1206,12 @@ function obligationWorkItem(item, byId, asOf) {
1199
1206
  profileId: item.completionProfile || null,
1200
1207
  resourceTypes: item.completionResourceTypes || []
1201
1208
  },
1202
- nextAction: obligationNextAction(item)
1209
+ nextAction: obligationNextAction(item, programId)
1203
1210
  };
1204
1211
  }
1205
1212
 
1206
- function obligationNextAction(item) {
1213
+ function obligationNextAction(item, programId) {
1214
+ const programOption = programId ? ` --program ${shellArgument(programId)}` : "";
1207
1215
  if (item.actionItemId) {
1208
1216
  if (item.status === "blocked") {
1209
1217
  return {
@@ -1213,12 +1221,30 @@ function obligationNextAction(item) {
1213
1221
  }
1214
1222
  return {
1215
1223
  kind: "command",
1216
- command: `npx filegrc complete-action ${shellArgument(item.actionItemId)} --scaffold --completed-on YYYY-MM-DD`
1224
+ command: `npx filegrc complete-action ${shellArgument(item.actionItemId)} --scaffold --completed-on YYYY-MM-DD${programOption}`
1225
+ };
1226
+ }
1227
+ if (item.ruleId && ["proposed", "approved"].includes(item.ruleStatus)) {
1228
+ return {
1229
+ kind: "command",
1230
+ command: `npx filegrc activate-obligation-rule ${shellArgument(item.ruleId)} --scaffold`
1231
+ };
1232
+ }
1233
+ if (item.programBlocker) {
1234
+ return {
1235
+ kind: "command",
1236
+ command: `npx filegrc get ${shellArgument(item.programBlocker.id)} --mutation`
1237
+ };
1238
+ }
1239
+ if (item.ruleId) {
1240
+ return {
1241
+ kind: "command",
1242
+ command: `npx filegrc reconcile-obligation ${shellArgument(item.obligationId)} --scaffold --window-start ${shellArgument(item.dueWindowStart)}${item.status === "complete" ? " --correct-finalized" : ""}${programOption}`
1217
1243
  };
1218
1244
  }
1219
1245
  return {
1220
1246
  kind: "command",
1221
- command: `npx filegrc complete ${shellArgument(item.obligationId)} --scaffold --window-start ${shellArgument(item.dueWindowStart)} --completed-on YYYY-MM-DD`
1247
+ command: `npx filegrc complete ${shellArgument(item.obligationId)} --scaffold --window-start ${shellArgument(item.dueWindowStart)} --completed-on YYYY-MM-DD${programOption}`
1222
1248
  };
1223
1249
  }
1224
1250