diff --git a/docs/data-model.md b/docs/data-model.md index d482409..57b523e 100644 --- a/docs/data-model.md +++ b/docs/data-model.md @@ -2443,7 +2443,7 @@ Timing: Collect real retained proof, then substantively review its source, scope When reviewing: - Collected means the artifact exists; Reviewed (stored as status verified) means a named Person actually checked it. Record that Person in verifierIds and the real review date in verifiedOn. The reviewer may be the collector. Do not infer review or independence from collection or fabricate review metadata. -- Preserve any specifically required independent review, including configuration proof supporting Reporting Channel Set approval. Keep independent policy and risk-assessment approvals and the CPA firm’s examination separate from routine evidence review. +- Preserve any specifically required independent review, including review of Reporting Channel Set configuration proof by someone independent of ongoing channel responsibility. That reviewer may also collect the proof. Keep independent policy and risk-assessment approvals and the CPA firm’s examination separate from routine evidence review. - For a signed management representation, choose "Signed Record" for "Artifact Kind" and enter "signed-management-representation" for "Artifact Subtype". - Enter when the representation was signed in "Business event time". Use "Collected On" for the date you received it. - For a final CPA report, choose "Third Party Report" for "Artifact Kind", enter "soc2-report" for "Artifact Subtype", and enter when the CPA firm issued it in "Source generation time". diff --git a/package-lock.json b/package-lock.json index b4be9c6..652ee36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "filegrc-monorepo", - "version": "0.21.11", + "version": "0.21.12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "filegrc-monorepo", - "version": "0.21.11", + "version": "0.21.12", "workspaces": [ "packages/filegrc", "packages/create-filegrc" @@ -24,7 +24,7 @@ "link": true }, "packages/create-filegrc": { - "version": "0.21.11", + "version": "0.21.12", "license": "MIT", "bin": { "create-filegrc": "bin/create-filegrc.js" @@ -34,7 +34,7 @@ } }, "packages/filegrc": { - "version": "0.21.11", + "version": "0.21.12", "license": "MIT", "bin": { "filegrc": "bin/filegrc.js" diff --git a/package.json b/package.json index b343043..a2df6b3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "filegrc-monorepo", - "version": "0.21.11", + "version": "0.21.12", "private": true, "workspaces": [ "packages/filegrc", diff --git a/packages/create-filegrc/package.json b/packages/create-filegrc/package.json index 1362079..db82f26 100644 --- a/packages/create-filegrc/package.json +++ b/packages/create-filegrc/package.json @@ -1,6 +1,6 @@ { "name": "create-filegrc", - "version": "0.21.11", + "version": "0.21.12", "description": "Create a filegrc workspace for a SOC 2 program", "license": "MIT", "repository": { diff --git a/packages/create-filegrc/src/index.js b/packages/create-filegrc/src/index.js index 5958baf..437296d 100644 --- a/packages/create-filegrc/src/index.js +++ b/packages/create-filegrc/src/index.js @@ -524,13 +524,13 @@ async function runCombinedSetup(target, input) { async function writeMinimalLockfile(target, name, versionRange) { const lock = { name, - version: "0.21.11", + version: "0.21.12", lockfileVersion: 3, requires: true, packages: { "": { name, - version: "0.21.11", + version: "0.21.12", dependencies: { filegrc: versionRange } } } diff --git a/packages/create-filegrc/template/package.json b/packages/create-filegrc/template/package.json index 68e7835..7cafe56 100644 --- a/packages/create-filegrc/template/package.json +++ b/packages/create-filegrc/template/package.json @@ -1,6 +1,6 @@ { "name": "{{project_name}}", - "version": "0.21.11", + "version": "0.21.12", "private": true, "description": "filegrc workspace for a SOC 2 program", "type": "module", diff --git a/packages/filegrc/model/v13.json b/packages/filegrc/model/v13.json index 46c437a..c2e208d 100644 --- a/packages/filegrc/model/v13.json +++ b/packages/filegrc/model/v13.json @@ -1809,7 +1809,7 @@ "emptyState": "No Evidence Artifacts have been collected. Add one only when a real retained artifact or approved external reference exists.", "reviewPoints": [ "Collected means the artifact exists; Reviewed (stored as status verified) means a named Person actually checked it. Record that Person in verifierIds and the real review date in verifiedOn. The reviewer may be the collector. Do not infer review or independence from collection or fabricate review metadata.", - "Preserve any specifically required independent review, including configuration proof supporting Reporting Channel Set approval. Keep independent policy and risk-assessment approvals and the CPA firm\u2019s examination separate from routine evidence review.", + "Preserve any specifically required independent review, including review of Reporting Channel Set configuration proof by someone independent of ongoing channel responsibility. That reviewer may also collect the proof. Keep independent policy and risk-assessment approvals and the CPA firm\u2019s examination separate from routine evidence review.", "For a signed management representation, choose \"Signed Record\" for \"Artifact Kind\" and enter \"signed-management-representation\" for \"Artifact Subtype\".", "Enter when the representation was signed in \"Business event time\". Use \"Collected On\" for the date you received it.", "For a final CPA report, choose \"Third Party Report\" for \"Artifact Kind\", enter \"soc2-report\" for \"Artifact Subtype\", and enter when the CPA firm issued it in \"Source generation time\"." diff --git a/packages/filegrc/package.json b/packages/filegrc/package.json index 9dee3ac..37afcd3 100644 --- a/packages/filegrc/package.json +++ b/packages/filegrc/package.json @@ -1,6 +1,6 @@ { "name": "filegrc", - "version": "0.21.11", + "version": "0.21.12", "description": "Zero-dependency Git-native GRC engine", "license": "MIT", "repository": { diff --git a/packages/filegrc/src/reporting-route-integrity.js b/packages/filegrc/src/reporting-route-integrity.js index b1e5b9f..75d639f 100644 --- a/packages/filegrc/src/reporting-route-integrity.js +++ b/packages/filegrc/src/reporting-route-integrity.js @@ -192,10 +192,11 @@ export function reportingRouteApprovalEvidence(loaded, routeSet, evidenceIds, ap const committed = getFileObjectIdAtRevision(loaded.root, materialCommit, `data/${path}`); return committed && committed === getWorkingFileObjectId(loaded.root, `data/${path}`); })) return false; - // Review must concern an existing proposal and be independent of collection - // and ongoing channel responsibility. Date-only records retain day precision. + // Review must concern an existing proposal and be independent of ongoing + // channel responsibility. The reviewer may collect the proof themselves. + // Date-only records retain day precision. if (evidence.verifiedOn < proposalDate - || arrayValue(evidence.verifierIds).some((id) => authorityIds.has(id) || arrayValue(evidence.collectorIds).includes(id))) return false; + || arrayValue(evidence.verifierIds).some((id) => authorityIds.has(id))) return false; for (const field of ["collectedAt", "verifiedAt", "sourceGeneratedAt", "businessEventAt", "generatedAt"]) { if (evidence[field] && (!isRfc3339Timestamp(evidence[field]) || new Date(evidence[field]) > decision)) return false; } diff --git a/packages/filegrc/test/reporting-route-sets.test.js b/packages/filegrc/test/reporting-route-sets.test.js index 0befc7d..a6b7cf3 100644 --- a/packages/filegrc/test/reporting-route-sets.test.js +++ b/packages/filegrc/test/reporting-route-sets.test.js @@ -905,7 +905,7 @@ test("reviews earlier fixed configuration against an unchanged proposal without ...source, artifactKind: "configuration-export", collectedOn: "2021-07-31", verifiedOn: "2021-08-01", collectedAt: "2021-07-31T14:00:00Z", verifiedAt: "2021-08-01T15:00:00Z", - collectorIds: ["person-example"], verifierIds: ["person-independent-approver-example"], + collectorIds: ["person-independent-approver-example"], verifierIds: ["person-independent-approver-example"], coverage: { kind: "as-of", on: "2021-07-31" } }; for (const field of ["generatedAt", "timezone", "queryDescription", "populationCount", "completenessValidation", "accuracyValidation"]) delete evidence[field]; @@ -922,6 +922,8 @@ test("reviews earlier fixed configuration against an unchanged proposal without return reportingRouteApprovalEvidence(current, candidate, [evidence.id], decision, "UTC"); }; assert.equal((await support()).length, 1); + assert.equal((await support({ collectorIds: ["person-example"] })).length, 1); + assert.equal((await support({ collectorIds: ["person-example"], verifierIds: ["person-example"] })).length, 0); for (const patch of [ { status: "collected" }, { verifierIds: ["person-example"] }, { collectorIds: ["person-route-authority-successor"], verifierIds: ["person-example"] },