filegrc 0.16.14 → 0.16.15

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "filegrc",
3
- "version": "0.16.14",
3
+ "version": "0.16.15",
4
4
  "description": "Zero-dependency Git-native GRC engine",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -167,7 +167,9 @@ function scopedProgramPeople(loaded, program = {}) {
167
167
  const systemIds = new Set(program.systemIds || []);
168
168
  const controlIds = new Set(program.controlIds || []);
169
169
  const policyIds = new Set(loaded.resources
170
- .filter(({ type, status, programRole }) => type === "policy" && status !== "retired" && programRole !== "reference")
170
+ .filter(({ type, status, programRole }) => (
171
+ type === "policy" && !["superseded", "retired"].includes(status) && programRole !== "reference"
172
+ ))
171
173
  .map(({ id }) => id));
172
174
  const components = programComponents(loaded, program);
173
175
  const componentIds = new Set(components.map(({ id }) => id));
@@ -177,13 +179,13 @@ function scopedProgramPeople(loaded, program = {}) {
177
179
  ]);
178
180
  const sources = loaded.resources.filter((record) => (
179
181
  ["workspace", "program", "appointment", "team"].includes(record.type)
180
- || record.type === "system" && systemIds.has(record.id)
182
+ || record.type === "system" && systemIds.has(record.id) && record.status !== "retired"
181
183
  || record.type === "component" && componentIds.has(record.id)
182
- || record.type === "vendor" && vendorIds.has(record.id)
183
- || record.type === "control" && controlIds.has(record.id)
184
+ || record.type === "vendor" && vendorIds.has(record.id) && !["deprecated", "terminated"].includes(record.status)
185
+ || record.type === "control" && controlIds.has(record.id) && record.status !== "retired"
184
186
  || record.type === "policy" && policyIds.has(record.id)
185
- || record.type === "document" && record.workflowScope !== "engagement"
186
- || record.type === "obligation" && (
187
+ || record.type === "document" && record.workflowScope !== "engagement" && !["superseded", "retired"].includes(record.status)
188
+ || record.type === "obligation" && record.status !== "retired" && (
187
189
  (record.controlIds || []).some((id) => controlIds.has(id))
188
190
  || (record.policyIds || []).some((id) => policyIds.has(id))
189
191
  )
@@ -1239,7 +1239,7 @@ function requiredGovernedDocuments(scope, records, byId, model) {
1239
1239
  const selectedControlIds = new Set(scope.controls.map(({ id }) => id));
1240
1240
  const linkedDocumentIds = new Set(requiredPolicies(scope, byId).flatMap((policy) => policy.relatedDocumentIds || []));
1241
1241
  const obligationDocumentIds = new Set(records
1242
- .filter((record) => record.type === "obligation")
1242
+ .filter((record) => record.type === "obligation" && record.status !== "retired")
1243
1243
  .flatMap((record) => [
1244
1244
  ...(record.scopeResourceIds || []),
1245
1245
  ...(record.templateResourceId ? [record.templateResourceId] : [])
package/src/state.js CHANGED
@@ -344,7 +344,10 @@ async function createAppStateUnlocked(input, options) {
344
344
  function assessApplicabilityReviewStatuses(loaded, program) {
345
345
  const decisions = new Map((program.requirementApplicability || []).map((review) => [review.requirementId, review]));
346
346
  return Object.fromEntries(loaded.resources
347
- .filter(({ type }) => ["requirement", "control", "commitment", "complementary-control"].includes(type))
347
+ .filter(({ type, status }) => (
348
+ ["requirement", "control", "commitment", "complementary-control"].includes(type)
349
+ && !["retired", "superseded"].includes(status)
350
+ ))
348
351
  .map((record) => {
349
352
  const review = record.type === "requirement" && modelSupports(loaded.model, "program-scope")
350
353
  ? decisions.get(record.id)
package/src/web.js CHANGED
@@ -1897,11 +1897,13 @@ function derivedStagePageState(stage, destination) {
1897
1897
  : { complete: false, label: "Review scope" };
1898
1898
  }
1899
1899
  if (stage.id === "audit" && destination.type === "document" && destination.href.includes("documentScope=audit")) {
1900
- if (!resourcesOfType("document").some(({ record }) => auditSpecificDocument(record))) {
1900
+ if (!resourcesOfType("document").some(({ record }) => (
1901
+ auditSpecificDocument(record) && !["retired", "superseded"].includes(record.status)
1902
+ ))) {
1901
1903
  return { complete: false, countsTowardProgress: false, label: "Only if needed" };
1902
1904
  }
1903
1905
  }
1904
- if (destination.type && resourcesOfType(destination.type).length === 0) {
1906
+ if (destination.type && !resourcesOfType(destination.type).some(({ record }) => !["retired", "superseded"].includes(record.status))) {
1905
1907
  return { complete: false, countsTowardProgress: false, label: "Only if needed" };
1906
1908
  }
1907
1909
  return { complete: true, label: "Ready" };
@@ -2792,6 +2794,7 @@ function openNextAuditCycleDialog(prior) {
2792
2794
  }
2793
2795
 
2794
2796
  function controlApplicabilityPending(record) {
2797
+ if (["retired", "superseded"].includes(record.status)) return false;
2795
2798
  if (state.applicabilityReviewStatuses?.[record.id]) {
2796
2799
  return state.applicabilityReviewStatuses[record.id] !== "current";
2797
2800
  }
@@ -2802,6 +2805,7 @@ function controlApplicabilityPending(record) {
2802
2805
  }
2803
2806
 
2804
2807
  function applicabilityPending(record) {
2808
+ if (["retired", "superseded"].includes(record.status)) return false;
2805
2809
  if (state.applicabilityReviewStatuses?.[record.id]) {
2806
2810
  return state.applicabilityReviewStatuses[record.id] !== "current";
2807
2811
  }
package/src/workflow.js CHANGED
@@ -393,6 +393,7 @@ function recordFinalizationFindings(loaded, program) {
393
393
  const findings = [];
394
394
  for (const record of loaded.resources) {
395
395
  if (["workspace", "renderer-settings"].includes(record.type)) continue;
396
+ if (["retired", "superseded"].includes(record.status)) continue;
396
397
  const incomplete = recordIncompleteReason(record, loaded, program);
397
398
  if (incomplete) {
398
399
  findings.push(finalizationFinding(record, incomplete, loaded.model));
@@ -815,6 +816,9 @@ async function assessPeriodHealth(loaded, options) {
815
816
  .map(({ id }) => id));
816
817
  for (const record of loaded.resources) {
817
818
  if (record.type === "policy" && ["required", "alternative"].includes(record.programRole)) {
819
+ const historical = ["retired", "superseded"].includes(record.status);
820
+ const changedOn = record.statusTransition?.changedOn;
821
+ if (historical && changedOn && changedOn <= coverage.start) continue;
818
822
  if (record.status !== "active" || !record.effectiveOn || record.effectiveOn > coverage.start) {
819
823
  findings.push(periodGap(record, "policy", record.effectiveOn, coverage));
820
824
  }