Document {{ORG_PREFIX}}-006
Document & Record Control Procedure¶
1. Purpose¶
This procedure defines how {{ORG_NAME}} creates, reviews, approves, distributes,
protects, and retires the documented information of its integrated management
system (IMS), and how it captures and protects the records that evidence the
system operating. It operationalises the documentation commitments of
ims-scope-statement and is normative: the Git-based lifecycle in §3.2 is
the only way a controlled document reaches Approved status, and the append-only
records doctrine in §3.3.6 is the only way evidence is captured.
2. Scope¶
This procedure applies to:
- Controlled documents — every file under
docs/ims-core/,docs/policies/,docs/procedures/, anddocs/plans/in the IMS repository. - Records — every file under
docs/records/. - Registers — the Airtable base defined by
schemas/registers.schema.yml, in particular the Document Register and Policy Acknowledgements tables. - External documents the IMS depends on, controlled per §3.3.5: regulator guidance, the specifications a client hands over, and the standards {{ORG_NAME}} purchases.
It binds everyone who authors, reviews, approves, or reads IMS documentation,
including contractors. It does not cover general business files outside the
IMS repository, or the plain-language guides under docs/guides/ and training
pages under docs/training/, which are maintained pages rather than controlled
documents.
3. Procedure¶
3.1 Document control framework¶
3.1.1 What the IMS documentation comprises¶
{{ORG_NAME}}'s IMS documentation is one deliberate set: the core documents,
policies, procedures, and plans indexed in the Document Register and held
under docs/ims-core/, docs/policies/, docs/procedures/, and
docs/plans/, together with the records under docs/records/ that evidence
the system operating. The scope statement, the policy, and the objectives all
live inside this set. A document earns its place because {{ORG_NAME}} needs
it to run the system; the clause obligations each document serves are stated
in its clause_refs frontmatter.
The document set is sized for a ~25-person organisation: one integrated set covering both standards, no quality manual, and no document whose only job is to answer a clause heading. Anyone who finds a document adding no operational value challenges it through this procedure; padding it is never the fix.
Everything lives in one place, in three tiers:
| Tier | Content | Location | Mutability |
|---|---|---|---|
| Documents | Core docs, policies, procedures, plans | docs/ims-core/, docs/policies/, docs/procedures/, docs/plans/ |
Versioned; changed only via the lifecycle in §3.2 |
| Records | Point-in-time evidence | docs/records/ |
Append-only (§3.3.6) |
| Registers | Live status, schedule, and people indexes | Airtable, per schemas/registers.schema.yml |
Continuously updated; an index, never evidence |
3.1.2 Document identification¶
Every controlled document carries frontmatter that names it and states what
it is, who owns it, and where it sits in its lifecycle; those fields are
defined solely in schemas/document-types.yml (no ad-hoc
fields; tools/check_docs.py fails CI on any deviation):
- Document ID —
{{ORG_PREFIX}}-NNN, one single sequence across all document types. The type lives in thedocument_typefrontmatter field, never in the ID. IDs are never reused or renumbered; the next free NNN is reserved by creating the Document Register row before the branch is opened. - Filename — the lowercase hyphenated slug of the document title. Renaming a document means renaming the file in the same change.
- How it is held: plain-text Markdown with YAML frontmatter, in the private Git repository, rendered in the browser by GitHub. The file in the repository is the controlled copy; exported copies (PDF, print) are uncontrolled the moment they are made.
3.2 Creating and updating¶
No document reaches main without passing through the Git lifecycle below:
the role named in its reviewer frontmatter examines every new draft and
every revision and approves on the pull request (step 5), and the role named
in its approver frontmatter merges (step 6).
The merge is the approval event: there is no separate sign-off form,
wet signature, or approval email.
3.2.1 Lifecycle steps (normative)¶
| Step | Action | Responsible role | Output / record |
|---|---|---|---|
| 1 | For a new document: reserve the next {{ORG_PREFIX}}-NNN by creating the Document Register row (Status: Draft). For a revision: locate the existing row. |
Document owner (the role in the document's owner frontmatter) |
Document Register row |
| 2 | Create branch doc/<ID>-<slug> and draft or revise the document from the matching templates/ skeleton: complete frontmatter per schemas/document-types.yml, bump version, and add a Revision History row describing the change. Push as often as convenient — CI runs tools/check_docs.py on every push, so frontmatter problems surface before any human reviews. |
Document owner | Branch, commits, green CI run |
| 3 | Sync the Document Register row (version, status, dates) as part of the same change — never as a later cleanup. tools/airtable_drift.py catches drift that discipline misses. |
Document owner | Updated register row |
| 4 | Hand-off: open a pull request using the PR template, request review from the role named in the document's reviewer frontmatter (GitHub sends the notification), and set status: Under Review with a matching register sync. The PR checklist covers: scope still accurate, clause refs resolve, revision-history row added, consultation record linked if worker_consultation_required: true, register row updated. |
Document owner | Pull request with completed checklist |
| 5 | Review: comments, requested changes, and re-work happen on the PR. The reviewer approves in the GitHub web UI once the PR checklist is satisfied and the document is accurate, complete, and something {{ORG_NAME}} can run as written. | Reviewer (per frontmatter) | PR review approval |
| 6 | Approval: the role named in the document's approver frontmatter gives the final approving review and merges. The final commit before merge flips status: Approved, sets approved_date, and syncs the Document Register row. The merge commit is the durable approval evidence. |
Approver (per frontmatter) | Merge commit to main; register row at Approved |
| 7 | If the document has acknowledgement_required: true and this is an approval or major revision, open an acknowledgement campaign (§3.4). |
{{ROLE_DOCUMENT_CONTROLLER}} | Campaign view; later, snapshot record |
Enforcement: branch protection on main — an approving review is required
and direct pushes are blocked — makes this sequence mandatory rather than
conventional. It is configured per instance during instantiation and is never
lifted for convenience; urgent changes go through the same steps on an
expedited timeline.
Separation of duties is enforced structurally: owner ≠ approver and
reviewer ≠ approver on every document, checked by tools/check_docs.py.
3.2.2 Version and revision-history rules¶
- Every change to a controlled document bumps
version, adds a Revision History row, and syncs the Document Register row — all in the same change. - Minor version (0.1 → 0.2): corrections and clarifications that do not change what anyone must do. Major version (1.0 → 2.0): changes to responsibilities, steps, or commitments. [ORG-DECISION: whether a major revision of an acknowledgement-required document always reopens the acknowledgement campaign, or only when the approver judges the change material.]
- A superseded document is never deleted: its status becomes
Supersededand its history remains in Git. Predecessor lineage from pre-IMS legacy documents is carried in thesupersedesfield and the Legacy ID register column, per the convention at the foot of this document.
3.2.3 Review cadence¶
next_review_date is required in every status — drafts have review
cadence too, so a half-written document cannot quietly rot on a branch.
- Cadences come from
org-profile.yml(review_cadence.draft_daysandreview_cadence.approved_days); a per-document override is simply a different date. - The Document Register's Review Status formula flags overdue items, including drafts ("Stale draft"); the weekly A1 digest emails each owner their overdue and due-soon documents.
- A review that concludes no change is needed is still evidenced: add a
Revision History row ("Reviewed, no changes"), bump
last_reviewed_date, set the newnext_review_date, and sync the register — via the lifecycle in §3.2.1. Document history lives in the document itself, not indocs/records/.
3.3 Control of documents¶
3.3.1 Availability, distribution, access and retrieval¶
The current approved version of every controlled document is whatever is on
main — there is exactly one distribution point, so stale copies cannot
circulate as controlled documents. GitHub renders Markdown in the browser, so
readers need no Git skills or local tooling; the reader guide in docs/guides/
explains access step by step. The generated document index (docs/index.md)
and the Document Register are the retrieval aids: both point at the file on
main, and neither is ever the document itself.
3.3.2 Worker access¶
All workers, including contractors engaged on {{ORG_NAME}} work, have read access to the IMS repository for the documented information relevant to them, and the {{ROLE_WORKER_REP}} has read access to the full document set and the consultation records that concern workers. [ORG-DECISION: the access mechanism for workers and contractors who do not hold GitHub accounts — e.g. read-only accounts provisioned at onboarding, or controlled distribution of rendered copies by the {{ROLE_DOCUMENT_CONTROLLER}}.] Access questions or barriers are raised with the {{ROLE_DOCUMENT_CONTROLLER}} through the channels in the communication and consultation arrangements.
3.3.3 Storage, preservation and protection¶
The private GitHub repository is the single authoritative store, and full
history is replicated to every clone. The {{ROLE_DOCUMENT_CONTROLLER}} grants
repository access per person, read for all workers and write for authors, and
revokes it at offboarding, so each document reaches the people who need it and
nobody else. Every document carries a Public, Internal, or Confidential
classification in its frontmatter, and Confidential documents are handled per
[ORG-DECISION: handling rule for Confidential-classified documents, e.g.
restricted repository or access list]. Branch protection keeps unreviewed
changes off main, and Git attributes and timestamps every change to a named
account, so nobody alters a controlled document without the change showing.
Plain-text Markdown keeps documents readable for as long as {{ORG_NAME}} holds
them: it does not decay or corrupt silently, it opens without proprietary
software, and Git history preserves every prior version.
3.3.4 Change control, retention and disposition¶
A controlled document changes only through the branch, pull request, review, and merge lifecycle in §3.2, and every change bumps the version, adds a Revision History row, and syncs the Document Register row in the same change, so the current version and the reason it changed always travel together. The private Git repository holds the whole history behind that current version.
Controlled documents and their full history stay in Git indefinitely, and a superseded version remains retrievable years later. Records are kept for their full retention period, set at instantiation: [ORG-DECISION: minimum retention periods for record categories, reflecting the organisation's legal and contractual obligations; never assumed here.] Nothing is disposed of inside its retention period.
{{ORG_NAME}} retires a document without deleting it: the document goes to
Superseded, or its gating feature_flag is turned off at instantiation, and
it stays in the repository with its Document Register row and full history
intact.
3.3.5 Documents of external origin¶
The IMS also depends on documents {{ORG_NAME}} does not write: the ISO standards themselves, client specifications, codes of practice, and regulator guidance. Each is tracked and kept current as follows:
- Each is indexed as an external-origin entry in the Document Register (source, version/edition, where it is held, which internal documents rely on it), so a revision of the external document triggers review of the internal documents that cite it.
- Copyrighted standards are held as licensed copies outside the repository (their location recorded in their Document Register entry), are never committed, published, or distributed, and are never quoted verbatim in IMS documents; the clause maps describe, in the system's own words, how each requirement is answered.
- The {{ROLE_DOCUMENT_CONTROLLER}} checks external-origin register entries for currency at least at each document review cycle, and records the outcome as a "Reviewed, no changes" event on the citing documents where applicable.
3.3.6 Records: append-only evidence¶
{{ORG_NAME}} keeps every record under docs/records/ exactly as it was
logged, and the repository itself is what holds it that way:
- Records are append-only. A record, once committed, is never edited,
amended, or rebased. The Git commit timestamp is the evidence of when the
record was logged;
activity_datein the record's frontmatter states when the activity happened. - A record found to be wrong is corrected by adding a new record that identifies the erroneous one and states the correction — never by changing the original.
- Record filenames follow
YYYY-MM-<slug>.mdand live in the subfolder for their record type, per the authoritative subfolder list inschemas/document-types.yml. Records carry the small record frontmatter (record type, title, activity date, evidencing register, related documents), not the controlled-document lifecycle — no version, no status, no approval. - Registers index; records evidence. An Airtable row saying an activity happened is a pointer, never the proof — the proof is the committed record. An empty records subfolder is the honest state until the activity it evidences has actually run.
3.4 Acknowledgement campaigns¶
For documents with acknowledgement_required: true, acknowledgement is
tracked per person per released version:
- Open — on approval or major revision (step 7 of §3.2.1), the {{ROLE_DOCUMENT_CONTROLLER}} opens a campaign: an Airtable view of active People (staff and contractors) crossed with the document, filtered to those with no Policy Acknowledgements row at the current version.
- Notify — automation A2 emails each person in the view the document link and the acknowledgement form link; each submitted form creates one Policy Acknowledgements row.
- Remind — automation A3 re-emails non-responders weekly.
- Close honestly — the campaign closes when the view empties, or at the deadline of [ORG-DECISION: campaign deadline, e.g. 10 working days] with the outstanding names recorded, never silently marked complete.
- Snapshot —
tools/snapshot_register.py acknowledgementswritesdocs/records/acknowledgements/YYYY-MM-<doc-slug>-vX.Y.mdcapturing who acknowledged which version, when, and who remained outstanding; the commit is the per-person evidence. The Policy Acknowledgements register remains the live index only.
This procedure itself carries acknowledgement_required: false; authors,
reviewers, and approvers demonstrate awareness of it by operating it.
3.5 Generated views¶
Every index or summary view of the document set (docs/index.md and its
siblings) is generated by tools/gen_views.py, committed, and diff-checked in
CI. Generated views are never hand-edited — a hand edit is a CI failure,
not a shortcut. Anyone needing a view changed changes the generator or the
source data, via the lifecycle in §3.2 where a controlled document is the
source.
4. Records and Registers¶
| Activity | Register (index) | Record (evidence) |
|---|---|---|
| Document lifecycle (draft, review, approval, review-no-change) | Document Register — one row per controlled document, mirroring frontmatter; drift-checked by tools/airtable_drift.py |
The Git history itself: commits, PR reviews, and merge commits on main are the durable evidence; no separate docs/records/ entry is written |
| Acknowledgement campaigns | Policy Acknowledgements — one row per person per required document version | docs/records/acknowledgements/YYYY-MM-<doc-slug>-vX.Y.md campaign snapshots |
Honest status: docs/records/acknowledgements/ stays empty until the first
real campaign has run and been snapshotted. A procedure that has never
produced its evidence has never run, and this document does not claim
otherwise.
5. Exceptions¶
An exception to this procedure (for example, a temporary alternative access arrangement under §3.3.2) is requested in writing to the {{ROLE_DOCUMENT_CONTROLLER}}, who assesses the impact and refers it to {{ROLE_TOP_MANAGEMENT}} for approval. An approved exception is logged in the Document Register notes for the affected document(s) and is valid for at most [ORG-DECISION: exception validity period, e.g. 90 days] before re-review.
No exception is available to: the append-only rule for docs/records/
(§3.3.6), branch protection on main (§3.2.1), or the prohibition on
hand-editing generated views (§3.5). Urgent document changes follow the normal
lifecycle on an expedited timeline — the reviewer and approver can act within
hours when needed.
6. Related Documents¶
ims-scope-statement— the IMS core document this procedure implements (implementsfrontmatter); it defines the system whose documentation this procedure controls.schemas/document-types.yml— the single source of truth for frontmatter fields, document types, and records subfolders (a schema, not a controlled document).schemas/registers.schema.yml— the specification of the Document Register, Policy Acknowledgements, and the other Airtable registers.docs/guides/— plain-language reader and author/reviewer/approver guides (maintained pages, not controlled documents), written to the lifecycle in §3.2.
7. Revision History¶
| Version | Date | Author | Description of Changes | Reviewed By | Review Date | Approved By | Approval Date |
|---|---|---|---|---|---|---|---|
| 0.1 | 2026-07-16 | {{ROLE_DOCUMENT_CONTROLLER}} | Initial draft | — | — | — | — |
8. Document Control
| Document | {{ORG_PREFIX}}-006 |
|---|---|
| Type | Procedure |
| Version | 0.1 |
| Status | Draft |
| Owner | {{ROLE_DOCUMENT_CONTROLLER}} |
| Reviewer | {{ROLE_QUALITY_MANAGER}} |
| Approver | {{ROLE_TOP_MANAGEMENT}} |
| Next Review | 2026-08-15 |
| Classification | Internal |
Held in the document frontmatter, mirrored to the Document Register.