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
19 changes: 19 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -843,3 +843,22 @@ CRUD and hand-edited source files. Hosted runtimes must upgrade before repositor
publish applications. Preview binds current service facts; save rejects changed
bindings. Retirement records the actual owner, date and reason, preserves the
original decision and cannot reactivate an old application.


FileGRC 0.20 extends the model v13 application scope to explicit Source Coverage
populations. It introduces a compatibility line because older readers reject that
scope relationship, while preserving every existing field and record. Core 0.20
continues to read and operate unchanged 0.18 and 0.19 repositories with API contract
1. Adoption of a Source Coverage application requires the repository manifest and
lockfile to select 0.20 before its first committed decision. Upgrading later does
not legitimize an application created under an unsupported runtime.

Source Coverage applications use a separate exact projection of the source family,
coverage kind, source Component, declared population, collection and retrieval
methods, validity and preservation decisions. The existing service projections
remain unchanged so prior applications keep their exact bindings. Shared retention
resolution serves retention readiness, evidence-source completeness and operating
preparation; no interface infers proof retention from a resource type. Source data
expiration remains separate from retained control proof. The application names the
approved Information Types, purpose, cutoff fit, disposal implementation and holds,
without editing the rule or its independent approval.
6 changes: 3 additions & 3 deletions docs/data-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -1630,13 +1630,13 @@ Record Markdown: available when needed as an implicit companion file.

#### `retention-application`

An owner decision applying one unchanged independently approved retention rule to additional services. It preserves the original schedule approval and never changes the approved rule.
An owner decision applying one unchanged independently approved retention rule to additional services or an explicit Source Coverage population. It preserves the original schedule approval and never changes the approved rule.

Instructions: Apply the complete unchanged independently approved rule to actual services after owner review of purpose, cutoff, disposal, holds and duties.

Policy basis: Apply the complete approved rule, including record purpose, cutoff, period, disposition and holds. Matching a duration alone is insufficient. New categories, conflicting duties, unsupported disposal or any changed rule require normal independent schedule approval.

Timing: Review applicability when the service data use or disposal capability changes and include applications in periodic independent retention oversight. Use apply-retention-rule to scaffold exact bindings. Retire an obsolete application and record a new decision; preserve history. Requires a committed repository dependency and lockfile for FileGRC 0.19.2 or newer in the 0.19 line.
Timing: Review applicability when service data use, the declared evidence population or disposal capability changes and include applications in periodic independent retention oversight. Use apply-retention-rule to scaffold exact bindings. Retire an obsolete application and record a new decision; preserve history. Source Coverage applications require a committed FileGRC 0.20 dependency and lockfile. Existing service applications support adopted 0.19.2 or newer runtimes.

Path: `data/retention-applications/<id>.json`

Expand All @@ -1650,7 +1650,7 @@ Record Markdown: available when needed as an implicit companion file.
| `approvalId` | id | Yes | Independent schedule approval References: `collection-review` |
| `approvalRevision` | string | Yes | |
| `programId` | id | Yes | References: `program` |
| `scopeResourceIds` | array of id | Yes | Services covered References: `system`, `component`, `vendor` |
| `scopeResourceIds` | array of id | Yes | Services or evidence populations covered References: `system`, `component`, `vendor`, `source-coverage` |
| `informationTypeIds` | array of id | Yes | References: `information-type` |
| `reviewedScopeRevisions` | object (`string-map`) | Yes | |
| `reviewedById` | id | Yes | References: `person` |
Expand Down
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.19.3",
"version": "0.20.0",
"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.19.3",
"version": "0.20.0",
"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.19.3",
version: "0.20.0",
lockfileVersion: 3,
requires: true,
packages: {
"": {
name,
version: "0.19.3",
version: "0.20.0",
dependencies: { filegrc: versionRange }
}
}
Expand Down
16 changes: 16 additions & 0 deletions packages/create-filegrc/template/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,19 @@ an honest owner applicability decision, preview it, then save the preview with
approved rows and approval metadata unchanged. Use normal independent review for
material changes or when no existing rule fully fits. Include service applications
in periodic independent retention oversight.


Source Coverage populations can use the same owner application from FileGRC 0.20.
Upgrade the repository dependency and lockfile to the supported 0.20 runtime before
recording that application. This expands model v13 without a model migration.
Choose the exact Source Coverage and existing Information Types from the approved
rule, state the retained proof and its boundaries, and confirm the complete rule
fits. The application binds the source family, authoritative source, population,
collection method and preservation facts. Material changes require a new owner
review or normal independent rule review. Adding retrieval rehearsal Evidence or
changing an unrelated service does not rewrite an existing application.

Keep source expiration separate from retained proof. A rule for preserved audit
metadata, approvals, results or scoped exports does not extend the retention of raw
logs, backups or deleted customer content. Do not infer a retention category from
a source family or resource type. Preserve approved rules and prior applications.
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.19.3",
"version": "0.20.0",
"private": true,
"description": "filegrc workspace for a SOC 2 program",
"type": "module",
Expand Down
21 changes: 20 additions & 1 deletion packages/filegrc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ Model v12 requires a complete Program Obligation schedule-set review before acti

## Hosted runtime compatibility

A hosted application can run one tested stable patch per supported compatibility line. Before 1.0, the line is the minor version, such as `0.17.x`. From 1.0 onward, it is the major version, such as `1.x`. Core accepts stable repository versions in its own line, including both older and newer patches, while retaining workspace model, record validation, and API contract checks. Prereleases, malformed versions, and other lines are rejected. Build metadata does not change the line. Diagnostic views remain available for model errors, with failed validation; ordinary mutations stay blocked.
A hosted application can run one tested stable patch per supported compatibility line. Before 1.0, the line is the minor version, such as `0.17.x`. From 1.0 onward, it is the major version, such as `1.x`. Core accepts stable repository versions in its own line, including both older and newer patches, while retaining workspace model, record validation, and API contract checks. The 0.20 runtime also reads unchanged repositories in the supported 0.18 and 0.19 lines; older runtimes reject repositories that adopt 0.20. Prereleases, malformed versions, and other lines are rejected. Build metadata does not change the line. Diagnostic views remain available for model errors, with failed validation; ordinary mutations stay blocked.

Use `assessWorkspaceRuntimeCompatibility(root, { requiredApiContractVersion: 1 })` before presenting hosted operations. It returns `compatible`, `installedVersion`, `repositoryVersion`, `supportedLine`, `repositoryLine`, `dataModelVersion`, `supportedModelVersions`, `apiContractVersion`, and a nullable `reason`. Failures include a repair message. `workspaceEngineVersion` remains the raw lockfile reader; `assertWorkspaceEngineVersion` uses the compatibility policy and attaches the result to `error.compatibility` when rejecting an operation. Unmanaged workspaces may omit package files; package-managed workspaces still require a readable lockfile with a resolved version, including linked dependency targets.

Expand Down Expand Up @@ -157,3 +157,22 @@ Use normal independent schedule review for a new category or purpose, a changed
cutoff or period, conflicting duties, unsupported disposal, or a material exception.
An application cannot supply missing independent approval. Retire an obsolete
application and record a new owner decision when the service facts change.


From FileGRC 0.20, an owner can also select an exact Source Coverage population in
an approved rule application. Upgrade the repository dependency and lockfile to
0.20 before previewing or saving this decision. Model v13 remains supported without
a migration. Hosted services must install a runtime supporting 0.20 before the
repository adopts that line.

Select the retained proof and its existing approved Information Types explicitly.
Preview binds its source family, authoritative Component, declared population,
collection and retrieval method, validity dates and preservation facts. Changes to
those facts require a fresh applicability review; unrelated metadata and retrieval
rehearsal Evidence do not replace the approved decision. Original rules and
independent approval records remain unchanged.

A preservation rule covers the declared proof, such as control metadata, approvals,
results or scoped exports. It does not extend raw log retention or restore deleted
customer content. Keep those source retention decisions separate and use normal
independent review when a new category, purpose or period is needed.
9 changes: 5 additions & 4 deletions packages/filegrc/model/v13.json
Original file line number Diff line number Diff line change
Expand Up @@ -9651,10 +9651,10 @@
"pluralTitle": "Retention rule applications",
"group": "governance",
"collection": "retention-applications",
"description": "An owner decision applying one unchanged independently approved retention rule to additional services. It preserves the original schedule approval and never changes the approved rule.",
"description": "An owner decision applying one unchanged independently approved retention rule to additional services or an explicit Source Coverage population. It preserves the original schedule approval and never changes the approved rule.",
"guidance": {
"policyBasis": "Apply the complete approved rule, including record purpose, cutoff, period, disposition and holds. Matching a duration alone is insufficient. New categories, conflicting duties, unsupported disposal or any changed rule require normal independent schedule approval.",
"cadence": "Review applicability when the service data use or disposal capability changes and include applications in periodic independent retention oversight. Use apply-retention-rule to scaffold exact bindings. Retire an obsolete application and record a new decision; preserve history. Requires a committed repository dependency and lockfile for FileGRC 0.19.2 or newer in the 0.19 line."
"cadence": "Review applicability when service data use, the declared evidence population or disposal capability changes and include applications in periodic independent retention oversight. Use apply-retention-rule to scaffold exact bindings. Retire an obsolete application and record a new decision; preserve history. Source Coverage applications require a committed FileGRC 0.20 dependency and lockfile. Existing service applications support adopted 0.19.2 or newer runtimes."
},
"required": [
"status",
Expand Down Expand Up @@ -9717,9 +9717,10 @@
"relation": [
"system",
"component",
"vendor"
"vendor",
"source-coverage"
],
"label": "Services covered"
"label": "Services or evidence populations covered"
},
"informationTypeIds": {
"type": "array",
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.19.3",
"version": "0.20.0",
"description": "Zero-dependency Git-native GRC engine",
"license": "MIT",
"repository": {
Expand Down
8 changes: 4 additions & 4 deletions packages/filegrc/src/nonmaterial-amendments.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function hasAmendmentRuntimePin(loaded, commit = null) {
? runGitCommandSync(loaded.root, ["show", `${commit}:./package-lock.json`], { timeout: 5_000, maxBuffer: 2_000_000 })
: readFileSync(join(loaded.root, "package-lock.json"), "utf8");
const engine = JSON.parse(source)?.packages?.["node_modules/filegrc"];
return !engine?.link && runtimeCompatibilityLine(engine?.version) === "0.19.x";
return !engine?.link && ["0.19.x", "0.20.x"].includes(runtimeCompatibilityLine(engine?.version));
} catch { return false; }
}

Expand Down Expand Up @@ -56,14 +56,14 @@ export function nonmaterialAmendmentIssues(loaded, amendment) {
const issues = [];
const fail = (message) => issues.push({ severity: "error", code: "invalid-nonmaterial-amendment", resourceId: amendment.id, message });
if (!hasAmendmentRuntimePin(loaded)) {
fail("Upgrade and commit the repository dependency and lockfile to FileGRC 0.19 before adopting nonmaterial amendments. The 0.19 runtime can read older repositories but cannot add these records to an older pin.");
fail("Upgrade and commit the repository dependency and lockfile to the supported FileGRC 0.19 or 0.20 line before adopting nonmaterial amendments. Reading an older repository does not authorize new records under an older pin.");
return issues;
}
const rule = loaded.model.nonmaterialAmendments?.[amendment.category];
const head = getGitSummary(loaded.root).commit;
const eventCommit = firstCommit(loaded, amendment.id);
if (eventCommit && !hasAmendmentRuntimePin(loaded, eventCommit)) {
fail("The repository must adopt the 0.19 dependency and lockfile no later than its first amendment commit.");
fail("The repository must adopt a supported 0.19 or 0.20 dependency and lockfile no later than its first amendment commit.");
return issues;
}
const source = /^[a-f0-9]{40}$/.test(amendment.sourceCommit || "") && head
Expand Down Expand Up @@ -201,7 +201,7 @@ export function amendedResourceView(loaded, target, options = {}) {

export async function scaffoldNonmaterialAmendment(input, targetId, options = {}) {
const loaded = input?.resources ? input : await loadWorkspace(input);
if (!hasAmendmentRuntimePin(loaded)) throw new Error("Upgrade and commit the repository dependency and lockfile to FileGRC 0.19 before adopting nonmaterial amendments.");
if (!hasAmendmentRuntimePin(loaded)) throw new Error("Upgrade and commit the repository dependency and lockfile to FileGRC 0.19 or 0.20 before adopting nonmaterial amendments.");
const entry = loaded.entries.find(({ record }) => record.id === targetId);
if (!entry) throw new Error(`Resource "${targetId}" was not found.`);
const head = getGitSummary(loaded.root).commit;
Expand Down
Loading
Loading