Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions docs/data-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,30 @@ Key format: `namespace`.
| `rehearsalEvidenceIds` | array of id | No | Operating handoff rehearsal proof References: `evidence` |
| `procedureResourceIds` | array of id | No | Existing operating procedures References: `control`, `document` |

### `provider-access-reconciliation`

| Property | Type | Required | Notes |
| --- | --- | --- | --- |
| `componentId` | id | Yes | References: `component` |
| `populationEvidenceId` | id | Conditional | References: `evidence` Required when `boundary` is `direct`. Allowed when `boundary` is `direct`. |
| `accounts` | array of object (`provider-account-decision`) | No | Allowed when `boundary` is `direct`. |
| `boundary` | enum | Yes | Values: `direct`, `inherited`, `no-account-store` |
| `identityComponentId` | id | Conditional | References: `component` Required when `boundary` is `inherited`. Allowed when `boundary` is `inherited`. |
| `boundaryEvidenceIds` | array of id | Conditional | References: `evidence` Required when `boundary` is one of `inherited`, `no-account-store`. |
| `rationale` | string | Conditional | Required when `boundary` is one of `inherited`, `no-account-store`. |

### `provider-account-decision`

| Property | Type | Required | Notes |
| --- | --- | --- | --- |
| `accountReference` | string | Yes | |
| `disposition` | enum | Yes | Values: `authorized`, `provider-managed`, `removed`, `unresolved` |
| `subjectId` | id | No | References: `person`, `service-account` |
| `accessGrantIds` | array of id | No | References: `access-grant` |
| `rationale` | string | Conditional | Required when `authorizationKind` is `review-renewal`. |
| `resolutionEvidenceIds` | array of id | No | References: `evidence` |
| `authorizationKind` | enum | Conditional | Values: `access-grant`, `review-renewal`, `service-account-inventory` Required when `disposition` is `authorized`. Allowed when `disposition` is `authorized`. |

## Common fields

| Field | Type | Required | Meaning |
Expand Down Expand Up @@ -1786,7 +1810,7 @@ When reviewing:
- Confirm the review population is complete for every System and exact date or period in scope.
- Decide whether each person and service account still needs its exact access and privilege level.
- Confirm every removal, change, or exception has follow-up.
- For the selected access Control baseline, reconcile actual provider human and service-account exports with Access Grants. Retain a checked population export per source, including zero counts, record every grant decision and resolve count differences before completion.
- For the selected access Control baseline, retain actual provider populations and use sourceReconciliations to account for every row. Map human accounts to current authorization and owned service identities to Service Accounts, explain inherited identity stores and provider-managed exclusions, retain removal proof, and resolve unknown access. Account counts and Access Grant counts are separate.

Default sources: `policy-information-security`

Expand All @@ -1812,6 +1836,7 @@ Record Markdown: shown by default as an implicit companion file.
| `completedOn` | date | Conditional | Completed on Required when `status` is `complete`. Allowed when `status` is `complete`. |
| `cancellation` | object (`cancellation`) | Conditional | Required when `status` is `canceled`. Allowed when `status` is `canceled`. |
| `componentIds` | array of id | Yes | Components References: `component` |
| `sourceReconciliations` | array of object (`provider-access-reconciliation`) | No | Provider account reconciliation |

### Systems and Vendors

Expand Down Expand Up @@ -2336,8 +2361,8 @@ Markdown companions:
| `verifiedOn` | date | Conditional | Required when `status` is `verified`. |
| `expiresOn` | date | No | |
| `sourceResourceIds` | array of id | No | Relation group: `evidence-source-record`. References: `appointment`, `document`, `obligation`, `obligation-event`, `requirement`, `commitment`, `complementary-control`, `control`, `control-test`, `finding`, `exception`, `action-item`, `policy`, `policy-review`, `attestation`, `meeting`, `training`, `risk`, `risk-assessment`, `vendor`, `vendor-review`, `access-grant`, `access-review`, `vulnerability`, `vulnerability-scan`, `incident`, `exercise`, `backup-test`, `penetration-test`, `data-request`, `audit`, `audit-population`, `audit-request`, `source-coverage`, `control-activity`, `retention-schedule-item`, `requirement-mapping`, `obligation-rule`, `obligation-occurrence`, `reporting-route`, `reporting-route-set` |
| `filePaths` | array of data-path | Conditional | Required when `sourceKind` is `file` and `status` is one of `collected`, `verified`, `withdrawn`. Allowed when `sourceKind` is one of `file`, `system`, `rendered-page`, `authored-record`. |
| `externalReference` | object (`external-reference`) | Conditional | Required when `sourceKind` is `external-reference` and `status` is one of `collected`, `verified`, `withdrawn`. Allowed when `sourceKind` is one of `external-reference`, `system`. |
| `filePaths` | array of data-path | Conditional | Required when `sourceKind` is `file` and `status` is one of `collected`, `verified`, `withdrawn`. Allowed when `sourceKind` is one of `file`, `system`, `rendered-page`, `authored-record`, `component`. |
| `externalReference` | object (`external-reference`) | Conditional | Required when `sourceKind` is `external-reference` and `status` is one of `collected`, `verified`, `withdrawn`. Allowed when `sourceKind` is one of `external-reference`, `system`, `component`. |
| `sourceCommit` | string | Conditional | Required when `sourceKind` is `rendered-page` and `status` is one of `collected`, `verified`, `withdrawn`. |
| `capture` | object (`page-capture`) | Conditional | Required when `sourceKind` is `rendered-page` and `status` is one of `collected`, `verified`, `withdrawn`. Allowed when `sourceKind` is `rendered-page`. |
| `classificationId` | id | Conditional | Classification References: `classification` Required when `status` is one of `collected`, `verified`, `withdrawn`. |
Expand Down
6 changes: 6 additions & 0 deletions docs/upgrading-to-model-v13.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,9 @@ For an unchanged committed proposal, retain the fixed configuration export and i
If a Policy activated before approved channels became effective, the historical coverage gap remains. Record current work on its actual dates and assess the earlier gap through the normal program and audit workflows. Recollecting an unchanged capture or backdating approval does not resolve that gap.

Component-scoped operating results can cover a System through the Component’s `systemUses` relationship. Explicit result `systemIds` remain authoritative. For a Component shared by several Systems, link Evidence naming both the tested Component and the intended System; a broad source or Control link does not establish execution scope. A System result does not automatically cover every Component. Dates, completion, review, proof and occurrence reconciliation still apply.

Provider account counts are separate from Access Grant counts. Use the optional `access-review.sourceReconciliations` array to retain one review across all providers. A `direct` row names its Component, fixed `populationEvidenceId` and one account decision per opaque export row. The actual export count must equal the number of account rows, and the review's `populationCount` totals the direct sources. A captured authenticated UI population is valid when its actual capture time, source, filters, complete page population and accuracy checks are retained; describe its observed provenance rather than claiming an API or CSV export.

An `authorized` account names its Person or Service Account and `authorizationKind`: `access-grant` maps existing grants, `review-renewal` records the review's actual current authorization and rationale without inventing historical provisioning dates, and `service-account-inventory` uses the active owned service identity. All current grants still need decisions and account mappings. `provider-managed` accounts require a bounded rationale with no human/grant mapping. `removed` accounts require retained resolution Evidence. `unresolved` accounts prevent completion.

An `inherited` source names its `identityComponentId`, rationale and fixed `boundaryEvidenceIds`; the chain must end in a reconciled direct source. A `no-account-store` source retains rationale and configuration proof and cannot conceal an active grant. Neither boundary creates a fictional zero-account export. Evidence with `sourceKind: "component"` now supports fixed `filePaths` and `externalReference` while retaining its authoritative `sourceComponentId`. Keep sensitive account identifiers in the retained report outside Git and use opaque row references here. Existing reviews remain unchanged and use their previous checks until explicit source reconciliation is recorded. No new independent approval is added.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "filegrc-monorepo",
"version": "0.18.8",
"version": "0.18.9",
"private": true,
"workspaces": [
"packages/filegrc",
Expand Down
2 changes: 1 addition & 1 deletion packages/create-filegrc/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-filegrc",
"version": "0.18.8",
"version": "0.18.9",
"description": "Create a filegrc workspace for a SOC 2 program",
"license": "MIT",
"repository": {
Expand Down
4 changes: 2 additions & 2 deletions packages/create-filegrc/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -524,13 +524,13 @@ async function runCombinedSetup(target, input) {
async function writeMinimalLockfile(target, name, versionRange) {
const lock = {
name,
version: "0.18.8",
version: "0.18.9",
lockfileVersion: 3,
requires: true,
packages: {
"": {
name,
version: "0.18.8",
version: "0.18.9",
dependencies: { filegrc: versionRange }
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/create-filegrc/template/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "{{project_name}}",
"version": "0.18.8",
"version": "0.18.9",
"private": true,
"description": "filegrc workspace for a SOC 2 program",
"type": "module",
Expand Down
163 changes: 160 additions & 3 deletions packages/filegrc/model/v13.json
Original file line number Diff line number Diff line change
Expand Up @@ -2017,7 +2017,8 @@
"file",
"system",
"rendered-page",
"authored-record"
"authored-record",
"component"
]
}
},
Expand All @@ -2035,7 +2036,8 @@
"allowedWhen": {
"sourceKind": [
"external-reference",
"system"
"system",
"component"
]
}
},
Expand Down Expand Up @@ -5507,7 +5509,7 @@
"Confirm the review population is complete for every System and exact date or period in scope.",
"Decide whether each person and service account still needs its exact access and privilege level.",
"Confirm every removal, change, or exception has follow-up.",
"For the selected access Control baseline, reconcile actual provider human and service-account exports with Access Grants. Retain a checked population export per source, including zero counts, record every grant decision and resolve count differences before completion."
"For the selected access Control baseline, retain actual provider populations and use sourceReconciliations to account for every row. Map human accounts to current authorization and owned service identities to Service Accounts, explain inherited identity stores and provider-managed exclusions, retain removal proof, and resolve unknown access. Account counts and Access Grant counts are separate."
],
"sourceResourceIds": [
"policy-information-security"
Expand Down Expand Up @@ -5641,6 +5643,13 @@
"component"
],
"label": "Components"
},
"sourceReconciliations": {
"type": "array",
"items": "object",
"itemObjectType": "provider-access-reconciliation",
"label": "Provider account reconciliation",
"description": "Reconcile each actual provider account export, including accountable identities, mapped grants, bounded provider-managed exclusions, removals and unresolved rows. Use opaque row references; retain personal account identifiers outside Git."
}
},
"listFields": [
Expand All @@ -5654,6 +5663,13 @@
"scheduledFor",
"coverage",
"cancellation"
],
"scaffoldFields": [
"componentIds",
"grantDecisions",
"populationCount",
"exceptionCount",
"sourceReconciliations"
]
},
"vulnerability": {
Expand Down Expand Up @@ -11221,6 +11237,147 @@
}
},
"additionalProperties": false
},
"provider-access-reconciliation": {
"additionalProperties": false,
"required": [
"componentId",
"boundary"
],
"properties": {
"componentId": {
"type": "id",
"relation": [
"component"
]
},
"populationEvidenceId": {
"type": "id",
"relation": [
"evidence"
],
"requiredWhen": {
"boundary": "direct"
},
"allowedWhen": {
"boundary": "direct"
}
},
"accounts": {
"type": "array",
"items": "object",
"itemObjectType": "provider-account-decision",
"allowedWhen": {
"boundary": "direct"
},
"description": "One decision for each actual retained account row. Empty or omitted only when the checked provider export count is zero."
},
"boundary": {
"type": "enum",
"values": [
"direct",
"inherited",
"no-account-store"
]
},
"identityComponentId": {
"type": "id",
"relation": [
"component"
],
"requiredWhen": {
"boundary": "inherited"
},
"allowedWhen": {
"boundary": "inherited"
}
},
"boundaryEvidenceIds": {
"type": "array",
"items": "id",
"relation": [
"evidence"
],
"requiredWhen": {
"boundary": [
"inherited",
"no-account-store"
]
}
},
"rationale": {
"type": "string",
"requiredWhen": {
"boundary": [
"inherited",
"no-account-store"
]
}
}
}
},
"provider-account-decision": {
"additionalProperties": false,
"required": [
"accountReference",
"disposition"
],
"properties": {
"accountReference": {
"type": "string",
"description": "Unique opaque row reference into the retained export. Keep personal account identifiers outside Git."
},
"disposition": {
"type": "enum",
"values": [
"authorized",
"provider-managed",
"removed",
"unresolved"
]
},
"subjectId": {
"type": "id",
"relation": [
"person",
"service-account"
]
},
"accessGrantIds": {
"type": "array",
"items": "id",
"relation": [
"access-grant"
]
},
"rationale": {
"type": "string",
"requiredWhen": {
"authorizationKind": "review-renewal"
}
},
"resolutionEvidenceIds": {
"type": "array",
"items": "id",
"relation": [
"evidence"
]
},
"authorizationKind": {
"type": "enum",
"values": [
"access-grant",
"review-renewal",
"service-account-inventory"
],
"requiredWhen": {
"disposition": "authorized"
},
"allowedWhen": {
"disposition": "authorized"
}
}
}
}
},
"obligationActivities": {
Expand Down
2 changes: 1 addition & 1 deletion packages/filegrc/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "filegrc",
"version": "0.18.8",
"version": "0.18.9",
"description": "Zero-dependency Git-native GRC engine",
"license": "MIT",
"repository": {
Expand Down
Loading
Loading