create-filegrc 0.3.3 → 0.4.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.
Files changed (52) hide show
  1. package/README.md +6 -5
  2. package/package.json +1 -1
  3. package/src/cli.js +34 -5
  4. package/src/defaults.js +81 -112
  5. package/src/index.js +66 -14
  6. package/template/AGENTS.md +38 -16
  7. package/template/README.md +14 -5
  8. package/template/data/AGENTS.md +36 -12
  9. package/template/data/action-items/AGENTS.md +2 -2
  10. package/template/data/appointments/appointment-policy-owner.json +11 -0
  11. package/template/data/audits/AGENTS.md +1 -1
  12. package/template/data/documents/document-business-continuity-disaster-recovery.json +12 -12
  13. package/template/data/documents/document-business-continuity-disaster-recovery.md +1 -1
  14. package/template/data/documents/document-contractor-policy-acknowledgement.json +10 -11
  15. package/template/data/documents/document-contractor-training-acknowledgement.json +13 -12
  16. package/template/data/documents/document-data-retention-schedule.json +9 -11
  17. package/template/data/documents/document-employee-handbook-acknowledgement.json +10 -11
  18. package/template/data/documents/document-employee-policy-acknowledgement.json +10 -11
  19. package/template/data/documents/document-employee-training-acknowledgement.json +13 -12
  20. package/template/data/documents/document-incident-response-plan.json +12 -12
  21. package/template/data/documents/document-incident-response-plan.md +2 -2
  22. package/template/data/documents/document-soc2-management-assertion.json +2 -3
  23. package/template/data/documents/document-soc2-management-representation.json +2 -3
  24. package/template/data/documents/document-soc2-period-completeness.json +2 -3
  25. package/template/data/documents/document-soc2-system-description.json +2 -3
  26. package/template/data/evidence/AGENTS.md +3 -3
  27. package/template/data/obligation-events/AGENTS.md +2 -2
  28. package/template/data/obligations/AGENTS.md +1 -1
  29. package/template/data/people/person-program-lead.json +9 -0
  30. package/template/data/policies/AGENTS.md +1 -1
  31. package/template/data/policies/policy-anti-bribery-corruption.json +9 -15
  32. package/template/data/policies/policy-anti-bribery-corruption.md +1 -1
  33. package/template/data/policies/policy-clear-desk-screen.json +8 -14
  34. package/template/data/policies/policy-clear-desk-screen.md +1 -1
  35. package/template/data/policies/policy-data-protection-handling.json +10 -22
  36. package/template/data/policies/policy-data-protection-handling.md +2 -2
  37. package/template/data/policies/policy-employee-handbook.json +6 -16
  38. package/template/data/policies/policy-information-security.json +8 -40
  39. package/template/data/policies/policy-information-security.md +2 -2
  40. package/template/data/policies/policy-mobile-computing-communications.json +8 -18
  41. package/template/data/policies/policy-mobile-computing-communications.md +1 -1
  42. package/template/data/renderer.json +3 -1
  43. package/template/data/training/training-anti-bribery-high-risk-roles.json +1 -2
  44. package/template/data/training/training-privileged-sensitive-roles.json +1 -2
  45. package/template/data/training/training-secure-development.json +1 -2
  46. package/template/data/training/training-security-awareness.json +7 -9
  47. package/template/data/training/training-security-awareness.md +1 -1
  48. package/template/data/workspace.json +19 -8
  49. package/template/docs/filegrc-home.png +0 -0
  50. package/template/package.json +1 -1
  51. package/template-parameters.json +6 -1
  52. package/template/data/people/person-policy-owner.json +0 -10
package/src/index.js CHANGED
@@ -16,6 +16,7 @@ export async function createFilegrc(options = {}) {
16
16
  const parameterConfig = JSON.parse(await readFile(join(packageRoot, "template-parameters.json"), "utf8"));
17
17
  const target = resolve(options.target ?? "filegrc-program");
18
18
  const starter = normalizeStarterProfile(options.starter);
19
+ const repository = normalizeRepositoryOptions(options);
19
20
  if (options.setup && options.install === false) {
20
21
  throw new Error("Combined service setup requires installation. Remove --no-install or run filegrc setup after npm install.");
21
22
  }
@@ -38,6 +39,7 @@ export async function createFilegrc(options = {}) {
38
39
  await mkdir(target, { recursive: true });
39
40
  await copyTemplate(target, starter);
40
41
  await renderTemplate(target, parameterConfig, values, starter);
42
+ await writeRendererRepositorySettings(target, repository);
41
43
  await writeBaselineRecords(target, values.effective_date, starter);
42
44
  await applyStarterScope(target, starter, values.effective_date);
43
45
  const initialResourceCounts = await summarizeResources(target);
@@ -49,7 +51,7 @@ export async function createFilegrc(options = {}) {
49
51
  await writeMinimalLockfile(target, values.project_name, values.filegrc_version_range);
50
52
  }
51
53
  const joinedExistingWorktree = await isInsideGitWorktree(target);
52
- if (!joinedExistingWorktree) await run("git", ["init"], target);
54
+ if (!joinedExistingWorktree) await run("git", ["init", `--initial-branch=${repository.authoritativeBranch}`], target);
53
55
  const gitHead = await inspectGitHead(target);
54
56
  const setup = options.setup ? await runCombinedSetup(target, options.setup) : null;
55
57
  const resourceCounts = setup ? await summarizeResources(target) : initialResourceCounts;
@@ -67,7 +69,8 @@ export async function createFilegrc(options = {}) {
67
69
  install: installed ? "installed" : "skipped",
68
70
  gitMode: joinedExistingWorktree ? "existing-worktree" : "initialized",
69
71
  gitBranch: gitHead.branch,
70
- gitDetached: gitHead.detached
72
+ gitDetached: gitHead.detached,
73
+ repository
71
74
  };
72
75
  }
73
76
 
@@ -80,6 +83,54 @@ export function normalizeStarterProfile(value = "security") {
80
83
  return normalized;
81
84
  }
82
85
 
86
+ function normalizeRepositoryOptions(options) {
87
+ const mode = String(options.repositoryMode ?? "trunk").trim();
88
+ if (!["trunk", "manual"].includes(mode)) {
89
+ throw new Error("Repository mode must be trunk or manual.");
90
+ }
91
+ return {
92
+ mode,
93
+ authoritativeBranch: normalizeGitSetting(options.authoritativeBranch, "main", "authoritative branch"),
94
+ remote: normalizeGitSetting(options.repositoryRemote, "origin", "repository remote")
95
+ };
96
+ }
97
+
98
+ function normalizeGitSetting(value, fallback, label) {
99
+ const result = String(value ?? fallback).trim();
100
+ if (!safeGitName(result)) {
101
+ throw new Error(`${label} must be a safe Git name.`);
102
+ }
103
+ return result;
104
+ }
105
+
106
+ function safeGitName(value) {
107
+ const segments = value.split("/");
108
+ return Boolean(value)
109
+ && value !== "@"
110
+ && value !== "HEAD"
111
+ && !value.startsWith("-")
112
+ && !value.includes("..")
113
+ && !value.includes("@{")
114
+ && !/[\s~^:?*[\]\\\u0000-\u001f\u007f]/.test(value)
115
+ && segments.every((segment) => (
116
+ segment
117
+ && !segment.startsWith(".")
118
+ && !segment.endsWith(".")
119
+ && !segment.endsWith(".lock")
120
+ ));
121
+ }
122
+
123
+ async function writeRendererRepositorySettings(target, repository) {
124
+ const path = join(target, "data", "renderer.json");
125
+ const renderer = JSON.parse(await readFile(path, "utf8"));
126
+ await writeFile(path, `${JSON.stringify({
127
+ ...renderer,
128
+ repositoryMode: repository.mode,
129
+ authoritativeBranch: repository.authoritativeBranch,
130
+ repositoryRemote: repository.remote
131
+ }, null, 2)}\n`, "utf8");
132
+ }
133
+
83
134
  export async function resolveFilegrcVersion(explicitVersion) {
84
135
  if (explicitVersion) return cleanVersion(explicitVersion);
85
136
  try {
@@ -121,6 +172,7 @@ async function resolvePromptValues(parameters, options) {
121
172
  const mapped = {
122
173
  company_name: options.companyName,
123
174
  policy_owner_name: options.policyOwnerName,
175
+ policy_owner_job_title: options.policyOwnerJobTitle,
124
176
  policy_owner_email: options.policyOwnerEmail,
125
177
  security_contact_email: options.securityContactEmail,
126
178
  timezone: options.timezone
@@ -128,6 +180,7 @@ async function resolvePromptValues(parameters, options) {
128
180
  if (options.yes) {
129
181
  mapped.company_name ??= "Example Company";
130
182
  mapped.policy_owner_name ??= "Security Owner";
183
+ mapped.policy_owner_job_title ??= "Chief Executive Officer";
131
184
  mapped.security_contact_email ??= "security@example.com";
132
185
  }
133
186
  for (const key of Object.keys(mapped)) {
@@ -157,7 +210,7 @@ async function resolvePromptValues(parameters, options) {
157
210
  if (missing.length) {
158
211
  throw new Error(`Missing required values: ${missing.map(({ key }) => key).join(", ")}`);
159
212
  }
160
- for (const key of ["company_name", "policy_owner_name"]) {
213
+ for (const key of ["company_name", "policy_owner_name", "policy_owner_job_title"]) {
161
214
  if (/[\u0000-\u001f\u007f]/.test(mapped[key])) {
162
215
  throw new Error(`${key} must be a single line without control characters.`);
163
216
  }
@@ -321,7 +374,7 @@ async function summarizeResources(target) {
321
374
  for (const path of await collectFiles(join(target, "data"))) {
322
375
  if (extname(path) !== ".json") continue;
323
376
  const record = JSON.parse(await readFile(path, "utf8"));
324
- if (!record?.id || !record?.type || !record?.schemaVersion) continue;
377
+ if (!record?.id || !record?.type) continue;
325
378
  total += 1;
326
379
  counts[record.type] = (counts[record.type] || 0) + 1;
327
380
  }
@@ -371,7 +424,7 @@ The generated workspace starts with five structural records:
371
424
 
372
425
  - Workspace and renderer settings
373
426
  - The initial active owner
374
- - An inactive security and risk oversight team that still needs an independent chair
427
+ - A planned security and risk oversight team that still needs an independent chair
375
428
  - The filegrc Git repository as a governance system of record
376
429
  - A default 5x5 risk method and Public, Internal, Confidential, and Restricted data classifications
377
430
 
@@ -414,23 +467,22 @@ The starter policies, controls, and obligations are proposals. They do not state
414
467
 
415
468
  1. Run \`npx filegrc setup\` for guided service and goal setup, or use browser onboarding. Then finish Step 1 by adding the real reviewers and operators, finishing the oversight team, and confirming applicable criteria, commitments, material vendors, and in-scope systems.
416
469
  2. Review the starter policies, appoint a reviewer who is separate from the policy owner, and activate only the policies that match current practice. The reviewer will usually be another person in the organization, but may be external.
417
- 3. Review the starter control set, implement each applicable control with its actual procedure, scope, cadence, evidence sources, and implementation date, and confirm any linked Work Queue schedules are enabled. Marking a control implemented starts eligible schedules. Then record any complementary customer or subservice controls.
418
- 4. Preview External Evidence drafts with \`npx filegrc evidence-test-drafts --preview --json\`. Create them only after confirming applicable controls and authoritative source systems.
419
- 5. Run \`npx filegrc program-readiness --require-ready\`, record the management candidate period start when reliable evidence collection begins, maintain risk assessments and risks, update controls when needed, use Work Queue for scheduled work, and trigger Policy Events when changes create required actions.
420
- 6. Engage a CPA firm, record the separate firm-agreed period in an audit record, review filegrc Evidence and External Evidence, and prepare fieldwork.`
470
+ 3. Review the starter control set and implement each applicable Control with its actual procedure, scope, cadence, and authoritative evidence source Systems. Confirm every source is active, has the required evidence role and current access owners, and includes repeatable retrieval instructions in Record Markdown. Add the implementation date, confirm any linked Work Queue schedules are enabled, then record any complementary customer or subservice controls.
471
+ 4. Run \`npx filegrc program-readiness --require-ready\`, record the management candidate period start when reliable evidence collection begins, maintain risk assessments and risks, update controls when needed, use Work Queue for scheduled work, and trigger Policy Events when changes create required actions.
472
+ 5. Engage a CPA firm, record the separate firm-agreed period in an audit record, review filegrc Evidence and External Evidence, and prepare fieldwork.`
421
473
  };
422
474
  }
423
475
 
424
476
  function validateCombinedSetup(setup) {
425
477
  if (!setup) return;
426
478
  if (Array.isArray(setup) || typeof setup !== "object") throw new Error("setup must be a JSON object.");
427
- const required = ["serviceName", "boundary", "criticality", "dataClassification", "internetExposed"];
479
+ const required = ["serviceName", "boundary", "criticality", "classificationId", "internetExposed"];
428
480
  const missing = required.filter((name) => setup[name] === undefined || setup[name] === "");
429
481
  if (missing.length) throw new Error(`Combined setup is missing: ${missing.join(", ")}.`);
430
482
  }
431
483
 
432
484
  async function runCombinedSetup(target, input) {
433
- const setup = { programGoal: "none", ownerId: "person-policy-owner", ...input };
485
+ const setup = { programGoal: "none", ownerId: "person-program-lead", ...input };
434
486
  const args = [
435
487
  join(target, "node_modules", "filegrc", "bin", "filegrc.js"),
436
488
  "setup",
@@ -438,7 +490,7 @@ async function runCombinedSetup(target, input) {
438
490
  "--boundary", String(setup.boundary),
439
491
  "--owner", String(setup.ownerId),
440
492
  "--criticality", String(setup.criticality),
441
- "--classification", String(setup.dataClassification),
493
+ "--classification", String(setup.classificationId),
442
494
  "--internet-exposed", String(setup.internetExposed),
443
495
  "--program-goal", String(setup.programGoal),
444
496
  "--summary",
@@ -452,13 +504,13 @@ async function runCombinedSetup(target, input) {
452
504
  async function writeMinimalLockfile(target, name, versionRange) {
453
505
  const lock = {
454
506
  name,
455
- version: "0.3.3",
507
+ version: "0.4.0",
456
508
  lockfileVersion: 3,
457
509
  requires: true,
458
510
  packages: {
459
511
  "": {
460
512
  name,
461
- version: "0.3.3",
513
+ version: "0.4.0",
462
514
  dependencies: { filegrc: versionRange }
463
515
  }
464
516
  }
@@ -18,7 +18,7 @@ npx filegrc list person --json
18
18
  npx filegrc program-readiness --summary --json
19
19
  ```
20
20
 
21
- `program-path --next --json` gives agents the current step and first action. Use `--summary` for all six step statuses or `--current` for the current step’s full renderer Instructions, Use, Policy Basis, commands, and next actions. The general guide lists every supported action and record type. A type guide repeats that page guidance and adds timing, required and conditional fields, current relationship candidates, JSON location, and Markdown slots.
21
+ `program-path --next --json` gives agents the current step and first action. Use `--summary` for all five step statuses or `--current` for the current step’s full renderer Instructions, Use, Policy Basis, commands, and next actions. The general guide lists every supported action and record type. A type guide repeats that page guidance and adds timing, required and conditional fields, current relationship candidates, JSON location, and Markdown slots.
22
22
 
23
23
  For a new record, generate a mutation envelope:
24
24
 
@@ -56,11 +56,26 @@ Read `data/AGENTS.md` before changing records. More specific instructions inside
56
56
 
57
57
  Git supplies file authors, commit timestamps, messages, diffs, and revisions. Do not add fields such as `createdAt`, `updatedAt`, `createdBy`, `updatedBy`, or a second change log.
58
58
 
59
- Domain events still need explicit dates. Keep values such as `occurredOn`, `approvedOn`, `reviewedOn`, `completedOn`, and audit-period dates in their records.
59
+ Domain events still need explicit dates. Keep values such as `occurredOn`, `scheduledFor`, `approvedOn`, `completedOn`, and audit-period dates in their records.
60
60
 
61
- Make focused commits with messages that explain the reason for the change. The engine never creates commits automatically. Review the workspace diff, then use the commit action on Repository or the Git CLI. The renderer validates the workspace and requires an explicit message before it creates a commit.
61
+ Use a dedicated private repository for your FileGRC workspace. The browser commits and pushes each saved program change, so a standalone repository keeps the compliance audit trail separate from application development history.
62
62
 
63
- Pull before starting work when other people or agents may have changed the repository. Without a remote, the browser's Repository page creates a local commit and hides synchronization actions. With a remote, it pulls with rebase, refuses to pull over uncommitted files, and pushes immediately after it creates a commit. Agents and terminal users own Git synchronization and should run `git pull --rebase`, `git commit`, and `git push` directly. Do not create merge commits for routine synchronization.
63
+ - Prefer creating or cloning FileGRC as a standalone private repository.
64
+ - Run the editable browser from the authoritative branch's main checkout.
65
+ - Do not place a new FileGRC workspace inside an application monorepo unless the organization has explicitly chosen that structure.
66
+ - If FileGRC already lives in a monorepo, do not relocate it automatically.
67
+ - In a monorepo, never include application changes in FileGRC-generated commits.
68
+ - Treat detached and feature-branch copies as read-only unless an explicit development override is active.
69
+
70
+ New workspaces use trunk repository mode with `main` as the authoritative branch and `origin` as the remote. Each browser mutation checks the whole Git worktree, fetches the remote, fast-forwards only, rechecks the edited revision, writes through the normal domain function, validates the workspace, stages only this FileGRC workspace, creates a focused commit, and pushes it. Browser onboarding commits its related workspace, system, and renderer changes together.
71
+
72
+ The Repository page reports `Synced`, `Syncing`, `Not synced`, `Read-only checkout`, or `Git setup required`. Browser saves return after the validated local commit, then push in the background. Treat `Syncing` as locally durable but not yet durable on the remote, and wait for `Synced` before starting another write. A failed push keeps the local FileGRC commit and offers Retry sync when every ahead commit changes only this workspace. FileGRC never pushes an ahead commit that includes files outside this workspace, and it never merges, rebases, switches branches, resolves conflicts, or changes files outside the workspace.
73
+
74
+ Record lifecycle fields are the approval source. Draft, proposed, approved, and retired records may all live on the authoritative branch. Do not use Git branches to represent policy approval.
75
+
76
+ Manual mode requires an explicit `repositoryMode` in `data/renderer.json`. In manual mode, review the workspace diff and use the Repository controls or Git CLI. Agents and terminal users always own their Git synchronization and should pull, commit, and push directly. FileGRC does not replace repository authentication, authorization, branch protection, or review controls.
77
+
78
+ Use `npx filegrc serve --allow-non-authoritative-writes` only for local development in a task worktree. The override is visible in the UI and never commits or pushes.
64
79
 
65
80
  Do not rewrite or remove committed records that explain prior audit periods. Close or retire them. Delete only mistakes and uncommitted drafts.
66
81
 
@@ -68,6 +83,14 @@ Do not rewrite or remove committed records that explain prior audit periods. Clo
68
83
 
69
84
  `data/workspace.json` selects the model through `dataModelVersion`. The installed `filegrc` package owns the authoritative model. Do not copy or invent a local schema.
70
85
 
86
+ If the installed CLI reports that this workspace uses an unsupported model, start with:
87
+
88
+ ```sh
89
+ npx filegrc migrate --to-model 2 --preview --json
90
+ ```
91
+
92
+ Resolve every missing value, conflict, and manual action in the preview before applying the migration with the same options and `--yes`.
93
+
71
94
  Run these commands when working with records:
72
95
 
73
96
  ```sh
@@ -93,7 +116,7 @@ Headless agents get the same protection by exporting an edit payload with `fileg
93
116
 
94
117
  ## Renderer settings and onboarding
95
118
 
96
- `data/renderer.json` stores committed renderer preferences. New workspaces set `showOnboarding` to `true`. Completing or skipping onboarding sets it to `false`; the app does not commit that change.
119
+ `data/renderer.json` stores committed renderer and repository preferences. New workspaces set `showOnboarding` to `true`, `repositoryMode` to `trunk`, `authoritativeBranch` to `main`, and `repositoryRemote` to `origin`. In trunk mode, completing or skipping onboarding commits the related change and starts its background push.
97
120
 
98
121
  Onboarding explains the file and Git workflow, the program path, policy obligations, and Policy Events before covering report types and the final audit stage. It then collects the initial service boundary, owner, business criticality, highest data classification, internet exposure, and optional program goal. It creates or updates one `system` record and stores that selected system and the management goal on `workspace`. It does not select framework records, link controls to the service, or create evidence. Selecting Type 1 or Type 2 does not create an audit engagement. Completing onboarding opens the Step 1 overview so the user can add the real reviewers and operators, finish the oversight team, and confirm the criteria, commitments, vendors, and systems before approving policies.
99
122
 
@@ -115,12 +138,12 @@ Work Queue includes recurring obligations, Policy Event tasks, and every other o
115
138
  A calendar obligation’s recurrence anchor starts its first allowed cycle. Unless `window` narrows that range, completion is allowed from the cycle start through the day before the next cycle, and the item becomes overdue on the next cycle’s first day. Use **Record work** in Work Queue, or create and link a completion atomically with:
116
139
 
117
140
  ```sh
118
- npx filegrc complete obligation-id completion-record.json
141
+ npx filegrc complete obligation-id completion-record.json --expected-revision REVISION
119
142
  ```
120
143
 
121
144
  Keep prior completion links because the planner matches each dated record to its own period.
122
145
 
123
- Event obligations are templates. Do not mark a template complete or replace it for each occurrence. Use Trigger Work on Step 5 or run:
146
+ Event obligations are templates. Do not mark a template complete or replace it for each occurrence. Use Trigger Work on Step 4 or run:
124
147
 
125
148
  ```sh
126
149
  npx filegrc trigger person-started --occurred-on 2026-07-25 --subject person-new-worker --json
@@ -132,11 +155,11 @@ Run `npx filegrc obligations` first to preview every task, owner, deadline, and
132
155
  Complete an event action and link its new proof in one validated write:
133
156
 
134
157
  ```sh
135
- npx filegrc complete-action action-item-id completion-record.json --completed-on 2026-07-25
136
- npx filegrc complete-event obligation-event-id --completed-on 2026-07-25
158
+ npx filegrc complete-action action-item-id completion-record.json --completed-on 2026-07-25 --expected-revision REVISION
159
+ npx filegrc complete-event obligation-event-id --completed-on 2026-07-25 --expected-revision REVISION
137
160
  ```
138
161
 
139
- filegrc rejects a completion resource whose type does not match the obligation. It will close the event only after every action has its requested proof.
162
+ Read `REVISION` from `npx filegrc get RESOURCE_ID --mutation`. filegrc rejects a completion resource whose type does not match the obligation. It will close the event only after every action has its requested proof.
140
163
 
141
164
  ## Headless Markdown
142
165
 
@@ -162,11 +185,10 @@ The Evidence Ready gate requires:
162
185
 
163
186
  1. A management goal, selected systems, criteria, and controls.
164
187
  2. Active policies with completed text, separate management approval, real approval and effective dates, and linked controls.
165
- 3. Implemented controls with an owner, actual procedure, scope, cadence, evidence source, mappings, implementation date, and every eligible linked Work Queue schedule running.
166
- 4. Active authoritative systems with evidence source roles, access owners, and repeatable extraction instructions in Record Markdown.
167
- 5. A verified `test-export` or `test-capture` evidence record for each selected control family that relies on evidence from outside filegrc.
188
+ 3. Implemented Controls with an owner, actual procedure, scope, operation pattern, mappings, implementation date, and every required linked Work Queue schedule running.
189
+ 4. Every selected Control mapped to active authoritative Systems with the required evidence source roles, current access owners, and repeatable extraction instructions in Record Markdown.
168
190
 
169
- Onboarding does not create External Evidence records. After confirming the applicable controls and authoritative source Systems, run `npx filegrc evidence-test-drafts --preview --json` and review the proposed collection tests. Then run `npx filegrc evidence-test-drafts` to create the missing drafts. filegrc-managed records, such as risk assessments, meetings, vendor reviews, attestations, vulnerability scans, penetration tests, backup tests, exercises, exceptions, and findings, do not need a separate collection test. Put any fixed external artifact in an External Evidence record and link it from the operating record. For each created draft, choose its authoritative source System, attach or reference the real result, record its collector and classification, then have another person verify it.
191
+ Onboarding does not create External Evidence records. Complete authoritative source Systems as part of Control implementation. For every incomplete family in Program Readiness, update the Control with its authoritative evidence source Systems, then give each source the required evidence role, current access owners, and repeatable retrieval instructions in Record Markdown. Use `npx filegrc evidence-map --json` when you want only those source checks. During Step 4, create External Evidence only when a real artifact exists. Select its source System, attach or reference the result, link the Controls and operating record it supports, record its collector and classification, then have another person verify it before audit use.
170
192
 
171
193
  When the gate passes, set `workspace.candidatePeriodStart` to the date reliable evidence collection begins. Do not backdate it. `candidatePeriodStart` and `candidatePeriodEnd` express management’s target. They do not establish the final report period.
172
194
 
@@ -190,7 +212,7 @@ The audit record’s `typeOneAsOf`, `periodStart`, and `periodEnd` are the dates
190
212
 
191
213
  Review both evidence paths against the exact firm-agreed date or period:
192
214
 
193
- 1. filegrc Evidence consists of dated Step 5 operating records. Complete each applicable record, link it to the Controls it supports, record the result in structured fields or Markdown, and link any external artifact needed to support that result.
215
+ 1. filegrc Evidence consists of dated Step 4 operating records. Complete each applicable record, link it to the Controls it supports, record the result in structured fields or Markdown, and link any external artifact needed to support that result.
194
216
  2. External Evidence consists of verified `evidence` records from authoritative Systems. Confirm the source System, audit date or period, Control links, collector, verifier, and fixed attachment or approved external reference.
195
217
 
196
218
  Audit Readiness reports coverage for both paths. The packet includes the matching filegrc records and Markdown with Git history, plus External Evidence records, retained attachments, delivery indexes, and checksums.
@@ -217,7 +239,7 @@ Link a control test to its `audit-population` record when sampling applies. Link
217
239
 
218
240
  ## Content and approvals
219
241
 
220
- The seed policy owner is {{policy_owner_name}} at {{policy_owner_email}}, and the security reporting address is {{security_contact_email}}. Replace ownership or contacts when responsibilities change.
242
+ The initial program lead is {{policy_owner_name}}, {{policy_owner_job_title}}, at {{policy_owner_email}}. The separate Policy Owner Appointment records this person’s starting program authority, and the security reporting address is {{security_contact_email}}. Update the Person when their organizational position changes. End and replace Appointments when named authority moves to someone else.
221
243
 
222
244
  Appoint an independent management reviewer during policy review, not as a condition of defining the service boundary. The reviewer must be separate from the policy owner and able to challenge the owner’s decisions. Most organizations assign another internal leader or manager. An external reviewer is also allowed, and a one-person company needs one because no second internal person is available. The reviewer chairs Security and Risk Oversight and approves policies and governed documents.
223
245
 
@@ -8,6 +8,8 @@ filegrc gives founder-led engineering teams one place to adopt policies, impleme
8
8
 
9
9
  It is open source, MIT licensed, and runs locally.
10
10
 
11
+ Use a dedicated private repository for your FileGRC workspace. The browser commits and pushes each saved program change, so a standalone repository keeps the compliance audit trail separate from application development history.
12
+
11
13
  ```sh
12
14
  npx create-filegrc@latest company-grc
13
15
  cd company-grc
@@ -17,6 +19,8 @@ npm run serve
17
19
 
18
20
  Requires Node.js 20 or newer and Git.
19
21
 
22
+ Existing model v1 workspaces must run `npx filegrc migrate --to-model 2 --preview --json` after installing a model v2 package. Resolve every reported item before applying the same migration with `--yes`.
23
+
20
24
  ## How it works
21
25
 
22
26
  The repository is the program. There is no separate application database.
@@ -27,16 +31,21 @@ The repository is the program. There is no separate application database.
27
31
 
28
32
  Use the same source through the local web app, a text editor, the CLI, or CI. Browser and CLI actions call the same rules, so engineers and agents see the same validation and readiness results.
29
33
 
34
+ New workspaces use `main` as the authoritative browser branch. Browser saves fetch and fast-forward from `origin`, validate the change, and create a focused local commit. The UI then unlocks for navigation while Git push continues in the background. Other writes remain locked until the Repository status confirms `Synced`; a failed push keeps the local commit and offers Retry sync. Draft, proposed, approved, and retired records all live on that branch because record status, not a Git branch, represents approval.
35
+
36
+ Detached and feature-branch checkouts are read-only in the browser by default. Developers can run `npx filegrc serve --allow-non-authoritative-writes` for local task-worktree edits; that override never commits or pushes. CLI and agent workflows continue to manage Git explicitly.
37
+
30
38
  ## One path from setup to audit
31
39
 
32
40
  ![filegrc SOC 2 program overview](docs/filegrc-home.png)
33
41
 
34
- 1. **Define scope.** Confirm owners, criteria, commitments, vendors, and in-scope systems.
42
+ 1. **Define scope.** Confirm people, dated appointments, teams, criteria, commitments, vendors, and in-scope systems. For Systems that produce evidence, add their source roles, access owners, and retrieval instructions.
35
43
  2. **Approve policies.** Tailor the proposals and record separate owners and reviewers.
36
- 3. **Implement controls.** Add the real procedure, scope, cadence, and evidence source.
37
- 4. **Test evidence collection.** Collect and verify evidence from each authoritative system.
38
- 5. **Operate the program.** Work the queue, trigger Policy Events, maintain risks, and preserve dated evidence.
39
- 6. **Audit.** Record the CPA engagement and agreed period, support fieldwork, and build the packet.
44
+ 3. **Implement controls.** Add the real procedure, scope, operation pattern, and authoritative evidence Systems. Put calendar and event schedules in Obligations. Confirm every source is active and has the required role, access owners, and repeatable retrieval instructions before marking the Control implemented.
45
+ 4. **Operate the program.** Work the queue, trigger Policy Events, maintain risks, and preserve dated evidence.
46
+ 5. **Audit.** Record the CPA engagement and agreed period, support fieldwork, and build the packet.
47
+
48
+ Control implementation includes evidence-source readiness. Use `npx filegrc program-readiness --json` to find incomplete Control or System records. `npx filegrc evidence-map --json` remains available as a focused diagnostic. Create External Evidence during Step 4 only when a real export, report, screenshot, signed file, or approved external reference exists.
40
49
 
41
50
  The Program Overview shows what is done, what is blocked, and what to do next.
42
51
 
@@ -15,7 +15,7 @@ npx filegrc list RESOURCE_TYPE --json
15
15
  npx filegrc search "TERM" --json
16
16
  ```
17
17
 
18
- Use `program-path --next --json` to find the current lifecycle step and first action. Use `--summary` for all six step statuses or `--current` for the current step’s full renderer Instructions, Use, Policy Basis, commands, and next actions. Use `guide` before any unfamiliar create or status transition. It repeats the page guidance and reports required fields, fields required by a status, enum values, relationship types and candidates, Markdown slots, timing, and exact paths. Use `describe` only when you need the raw model definition.
18
+ Use `program-path --next --json` to find the current lifecycle step and first action. Use `--summary` for all five step statuses or `--current` for the current step’s full renderer Instructions, Use, Policy Basis, commands, and next actions. Use `guide` before any unfamiliar create or status transition. It repeats the page guidance and reports required fields, fields required by a status, enum values, relationship types and candidates, Markdown slots, timing, and exact paths. Use `describe` only when you need the raw model definition.
19
19
 
20
20
  ## Choose the right record
21
21
 
@@ -24,7 +24,9 @@ Use `program-path --next --json` to find the current lifecycle step and first ac
24
24
  - Work required on a schedule or event belongs in `obligation`.
25
25
  - A dated instance of work belongs in its activity type, such as `meeting`, `risk-assessment`, `access-review`, `vulnerability-scan`, `backup-test`, or `exercise`.
26
26
  - A fact that may change over time belongs in an inventory record, such as `person`, `system`, `asset`, `vendor`, or `access-grant`.
27
- - A dated Step 5 operating record proves that filegrc-managed work occurred. Put each fixed external artifact in an `evidence` record and link it from the operating record; never add an unexplained attachment.
27
+ - A Person’s `jobTitle` is their actual position in the organization. A named authority they hold, such as CISO, DPO, Policy Owner, or team chair, belongs in a dated `appointment` scoped to the workspace, team, or governed records.
28
+ - Team membership and chairs are authoritative on `team.memberIds` and `team.chairIds`.
29
+ - A dated Step 4 operating record proves that filegrc-managed work occurred. Put each fixed external artifact in an `evidence` record and link it from the operating record; never add an unexplained attachment.
28
30
  - Follow-up work belongs in `action-item`. A gap belongs in `finding`, a known threat belongs in `risk`, and an approved temporary departure belongs in `exception`.
29
31
  - An auditor request belongs in `audit-request`; the engagement itself belongs in `audit`.
30
32
 
@@ -43,7 +45,6 @@ The scaffold is a mutation envelope:
43
45
  ```json
44
46
  {
45
47
  "record": {
46
- "schemaVersion": 1,
47
48
  "id": "resource-type-human-name",
48
49
  "type": "resource-type",
49
50
  "title": "Human name"
@@ -93,7 +94,9 @@ JSON is for stable metadata used by validation, relationships, filters, schedule
93
94
 
94
95
  If `guide` marks a Markdown slot recommended, fill it before treating the deliverable as complete. Keep observations and report details in the source record’s Markdown. Create a Finding only for a confirmed gap that needs its own remediation lifecycle. Create an Action Item only when follow-up needs a separate assignee, deadline, and completion proof. Set each child record’s `sourceResourceId` to the record that produced it; do not maintain reverse Finding or Action Item arrays on the source. Do not put a report’s entire variable structure into new JSON fields.
95
96
 
96
- Use explicit business dates. Git records when a file changed, but it does not replace `occurredOn`, `assessmentDate`, `reviewedOn`, `completedOn`, or similar fields.
97
+ Store a relationship only on its authoritative record. Control Tests store `auditId`; External Evidence stores `auditIds`; Commitments store `systemIds` and `controlIds`; Controls store `policyIds` and `requirementIds`; Risks store `controlIds`; Systems store their direct `vendorId`. Use `references` to inspect derived inbound links.
98
+
99
+ Use explicit business dates. Git records when a file changed, but it does not replace `occurredOn`, `scheduledFor`, `completedOn`, `approvedOn`, or similar fields.
97
100
 
98
101
  ## Status changes
99
102
 
@@ -118,7 +121,7 @@ npx filegrc references RESOURCE_ID --json
118
121
  Delete only an uncommitted draft or a mistake:
119
122
 
120
123
  ```sh
121
- npx filegrc delete RESOURCE_TYPE RESOURCE_ID --yes
124
+ npx filegrc delete RESOURCE_TYPE RESOURCE_ID --yes --expected-revision REVISION
122
125
  ```
123
126
 
124
127
  filegrc rejects deletion that breaks references and removes owned Markdown with the JSON. Retire, close, cancel, supersede, or replace committed records that explain historical operation.
@@ -137,7 +140,7 @@ The JSON uses `filePaths: ["evidence/evidence-example/source-export.csv"]`. Comm
137
140
  Use the attachment command to copy a fixed file and update `filePaths` in one validated action:
138
141
 
139
142
  ```sh
140
- npx filegrc attach EVIDENCE_ID /path/to/source-export.csv
143
+ npx filegrc attach EVIDENCE_ID /path/to/source-export.csv --expected-revision REVISION
141
144
  ```
142
145
 
143
146
  It refuses symlinks, hidden destination names, and existing destination files.
@@ -145,24 +148,43 @@ It refuses symlinks, hidden destination names, and existing destination files.
145
148
  Remove a local attachment explicitly before deleting its evidence record:
146
149
 
147
150
  ```sh
148
- npx filegrc detach EVIDENCE_ID source-export.csv --yes
151
+ npx filegrc detach EVIDENCE_ID source-export.csv --yes --expected-revision REVISION
149
152
  ```
150
153
 
151
154
  filegrc will not delete an evidence record that still has local attachments.
152
155
 
153
156
  Never invent evidence, dates, approvals, results, people, or source-system details. If a required fact is unavailable, leave the record in a non-final state and report the missing input.
154
157
 
158
+ ## Implement Controls and Their Evidence Sources
159
+
160
+ Finish each applicable Control and its authoritative source Systems together. Use Program Readiness as the completion check:
161
+
162
+ ```sh
163
+ npx filegrc program-readiness --json
164
+ ```
165
+
166
+ The Control stage reports both Control implementation items and evidence-family source checks. Resolve them through the source records:
167
+
168
+ 1. Choose an existing System or scaffold the System that is authoritative for the family.
169
+ 2. Set the System to `active`, add the matching `evidenceSourceKinds`, and name current `evidenceOwnerIds`.
170
+ 3. Put the exact report, filters, date range, timezone, export format, and reconciliation steps in the System’s Record Markdown.
171
+ 4. Add the System ID to `evidenceSourceIds` on every Control in the family that it supports.
172
+ 5. Finish the Control’s owner, procedure, scope, operation pattern, mappings, and implementation date. Put every calendar or event schedule in an Obligation.
173
+ 6. Run `program-readiness --json` again and resolve every failed Control or source check before marking the Controls implemented or starting the candidate period.
174
+
175
+ Use `get RESOURCE_ID --mutation` and `update` so JSON and Markdown change together. `evidence-map --json` remains available when you want only the evidence-family checks. Do not create an Evidence record while designing or implementing a Control. Create External Evidence during Step 4 only when the real export, report, screenshot, signed file, or approved external reference exists.
176
+
155
177
  ## Scheduled and event work
156
178
 
157
179
  ```sh
158
180
  npx filegrc obligations --json
159
- npx filegrc complete OBLIGATION_ID completion-mutation.json
181
+ npx filegrc complete OBLIGATION_ID completion-mutation.json --expected-revision REVISION
160
182
  npx filegrc trigger EVENT_TYPE --occurred-on YYYY-MM-DD --subject RESOURCE_ID --json
161
- npx filegrc complete-action ACTION_ITEM_ID completion-mutation.json --completed-on YYYY-MM-DD
162
- npx filegrc complete-event OBLIGATION_EVENT_ID --completed-on YYYY-MM-DD
183
+ npx filegrc complete-action ACTION_ITEM_ID completion-mutation.json --completed-on YYYY-MM-DD --expected-revision REVISION
184
+ npx filegrc complete-event OBLIGATION_EVENT_ID --completed-on YYYY-MM-DD --expected-revision REVISION
163
185
  ```
164
186
 
165
- Run `obligations` before `trigger` to preview every Policy Event task, owner, deadline, and requested proof. Triggering creates the event and adds all linked Action Items to the Work Queue atomically. `complete` and `complete-action` validate the expected completion type and link the new record atomically. `complete-event` refuses to close the workflow until every action has its requested proof. For hour-based deadlines use `--occurred-at` with an RFC 3339 timestamp and timezone.
187
+ Read `REVISION` from `npx filegrc get RESOURCE_ID --mutation`. Run `obligations` before `trigger` to preview every Policy Event task, owner, deadline, and requested proof. Triggering creates the event and adds all linked Action Items to the Work Queue atomically. `complete` and `complete-action` validate the expected completion type and link the new record atomically. `complete-event` refuses to close the workflow until every action has its requested proof. For hour-based deadlines use `--occurred-at` with an RFC 3339 timestamp and timezone.
166
188
 
167
189
  ## Audit work
168
190
 
@@ -173,7 +195,7 @@ npx filegrc audit-readiness AUDIT_ID --json
173
195
  npx filegrc evidence-packet --audit AUDIT_ID --preview --json
174
196
  ```
175
197
 
176
- Run Program Readiness before creating the normal audit engagement. It checks scope, effective policies, implemented controls, evidence sources, and test captures without an audit ID. Fix readiness errors in source records. Do not edit packet output under `.filegrc/`. A delivery-ready filegrc packet means the management checks passed; the engagement team still judges evidence and performs the examination.
198
+ Run Program Readiness before creating the normal audit engagement. It checks scope, effective policies, implemented controls, and evidence mapping without an audit ID. Fix readiness errors in the Control and System records. Do not edit packet output under `.filegrc/`. A delivery-ready filegrc packet means the management checks passed; the engagement team still judges evidence and performs the examination.
177
199
 
178
200
  ## Finish every change
179
201
 
@@ -185,3 +207,5 @@ git diff
185
207
  ```
186
208
 
187
209
  Review every changed JSON, Markdown, and attachment. Confirm the diff contains no secrets, temporary files, source exports with prohibited data, or derived `.filegrc/` output. Make one focused commit whose message says why the compliance record changed.
210
+
211
+ These commands are for CLI and agent work, which continues to manage Git explicitly. Browser saves in trunk mode commit automatically from the configured authoritative branch, then push in the background while the UI reports `Syncing`. Do not start another write until it reports `Synced`. Do not use a feature branch as a record approval state, and never include application changes when this workspace lives in a monorepo.
@@ -5,7 +5,7 @@ Create an Action Item only when follow-up needs its own assignee, deadline, and
5
5
  For an event-generated action, do not weaken or extend its policy deadline by hand. Create the requested completion resource and close the action atomically:
6
6
 
7
7
  ```sh
8
- npx filegrc complete-action ACTION_ITEM_ID completion-mutation.json --completed-on YYYY-MM-DD
8
+ npx filegrc complete-action ACTION_ITEM_ID completion-mutation.json --completed-on YYYY-MM-DD --expected-revision REVISION
9
9
  ```
10
10
 
11
- filegrc rejects the wrong completion type. Mark ordinary Action Items `done` only after the work occurred, set `completedOn`, and link the completion record or evidence. Use `blocked` while a named dependency prevents work, and link that dependency with `blockingResourceIds`.
11
+ Read `REVISION` from `npx filegrc get ACTION_ITEM_ID --mutation`. filegrc rejects the wrong completion type. Mark ordinary Action Items `done` only after the work occurred, set `completedOn`, and link the completion record or evidence. Use `blocked` while a named dependency prevents work, and link that dependency with `blockingResourceIds`.
@@ -0,0 +1,11 @@
1
+ {
2
+ "id": "appointment-policy-owner",
3
+ "type": "appointment",
4
+ "title": "Policy Owner",
5
+ "status": "active",
6
+ "appointmentKind": "policy-owner",
7
+ "holderId": "person-program-lead",
8
+ "scopeResourceIds": ["workspace"],
9
+ "startsOn": "{{effective_date}}",
10
+ "responsibilities": "Own the information security program and the starter policies, controls, documents, training, and scheduled work until management assigns more specific accountable parties."
11
+ }
@@ -17,7 +17,7 @@ Preparation creates engagement-specific management documents and, for Type 2, po
17
17
 
18
18
  Review both evidence paths for the exact formal date or period:
19
19
 
20
- 1. filegrc Evidence consists of dated Step 5 operating records. Complete the record, link it to the applicable Controls, record the result in its fields or Markdown, and link any external artifact needed to support that result.
20
+ 1. filegrc Evidence consists of dated Step 4 operating records. Complete the record, link it to the applicable Controls, record the result in its fields or Markdown, and link any external artifact needed to support that result.
21
21
  2. External Evidence consists of verified `evidence` records from other Systems. Confirm the source System, date or period, Control links, collector, verifier, and fixed attachment or approved external reference.
22
22
 
23
23
  The packet compiles both paths. It includes filegrc records and Markdown with Git history, plus External Evidence records, retained attachments, delivery indexes, and checksums.
@@ -1,21 +1,18 @@
1
1
  {
2
- "schemaVersion": 1,
3
2
  "id": "document-business-continuity-disaster-recovery",
4
3
  "type": "document",
5
4
  "title": "Business Continuity and Disaster Recovery Plan",
6
5
  "status": "draft",
7
6
  "documentKind": "plan",
8
- "ownerIds": ["person-policy-owner"],
7
+ "ownerIds": [
8
+ "appointment-policy-owner"
9
+ ],
9
10
  "version": "1.0",
10
11
  "effectiveOn": "{{effective_date}}",
11
- "reviewCadence": {
12
- "mode": "calendar",
13
- "unit": "year",
14
- "interval": 1,
15
- "anchorDate": "{{effective_date}}"
16
- },
17
- "classification": "internal",
18
- "audience": ["employees", "contractors"],
12
+ "audience": [
13
+ "employees",
14
+ "contractors"
15
+ ],
19
16
  "acknowledgementRequired": true,
20
17
  "controlIds": [
21
18
  "control-policy-management",
@@ -23,6 +20,9 @@
23
20
  "control-backup-restoration",
24
21
  "control-continuity-exercise"
25
22
  ],
26
- "relatedDocumentIds": ["document-incident-response-plan"],
27
- "evidenceIds": []
23
+ "relatedDocumentIds": [
24
+ "document-incident-response-plan"
25
+ ],
26
+ "evidenceIds": [],
27
+ "classificationId": "internal"
28
28
  }
@@ -33,7 +33,7 @@ During a disruption, {{company_name}} will:
33
33
 
34
34
  ### Policy owner
35
35
 
36
- {{policy_owner_name}} owns this plan and keeps it current. The policy owner may delegate response duties but remains accountable for the plan.
36
+ The current Policy Owner owns this plan and keeps it current. The Policy Owner may delegate response duties but remains accountable for the plan.
37
37
 
38
38
  ### Security and risk oversight
39
39
 
@@ -1,20 +1,19 @@
1
1
  {
2
- "schemaVersion": 1,
3
2
  "id": "document-contractor-policy-acknowledgement",
4
3
  "type": "document",
5
4
  "title": "Contractor Policy Acknowledgement",
6
5
  "status": "draft",
7
6
  "documentKind": "attestation-template",
8
- "ownerIds": ["person-policy-owner"],
7
+ "ownerIds": [
8
+ "appointment-policy-owner"
9
+ ],
9
10
  "version": "1.0",
10
11
  "effectiveOn": "{{effective_date}}",
11
- "reviewCadence": {
12
- "mode": "calendar",
13
- "unit": "year",
14
- "interval": 1,
15
- "anchorDate": "{{effective_date}}"
16
- },
17
- "classification": "internal",
18
- "audience": ["contractors"],
19
- "controlIds": ["control-workforce-expectations"]
12
+ "audience": [
13
+ "contractors"
14
+ ],
15
+ "controlIds": [
16
+ "control-workforce-expectations"
17
+ ],
18
+ "classificationId": "internal"
20
19
  }