Skip to content

Code does not match site/compliance.html: forgelm approve / reject + forgelm approvals drive the dual-controlled sign-off ... every model promotion is dual-controlled and forensic… (CR-A01-009) #94

Open

Description

@cemililik

Wave 0 · theme D0-5: Documented controls that are not implemented · highest severity Critical · 6 finding(s) · effort small

Summary

The document states: forgelm approve / reject + forgelm approvals drive the dual-controlled sign-off ... every model promotion is dual-controlled and forensically attributed.. Observed in the code: The approval gate is opt-in (evaluation.require_human_approval defaults to False, forgelm/config.py:1220-1223), so by default no promotion is gated at all. When the gate is on, the approver identity is just the unauthenticated FORGELM_OPERATOR value or the getpass username (forgelm/cli/subcommands/_approve.py:121-170, 603). No check makes the approver differ from the trainer, so one person can train and approve.

Primary finding

CR-A01-009 — Code does not match site/compliance.html: forgelm approve / reject + forgelm approvals drive the dual-controlled sign-off ... every model promotion is dual-controlled and forensicall

severity High · reachability default · intent contract-violation · confidence confirmed · independently confirmed

What happens. This is a C1 promise (F-114) that the code does not deliver. The approved threat model (TM-v1) puts approver authentication and approver-differs-from-trainer checks out of scope, so the realistic fix is probably the document. The project owner should decide whether to implement separation of duties or withdraw the claim.

Where.

Evidence.

  • forgelm/config.py:1220-1223; forgelm/cli/subcommands/_approve.py:121-170; forgelm/cli/subcommands/_approve.py:587-620

Recommended fix. Reword: 'Optional (opt-in) staging gate: when evaluation.require_human_approval: true, promotion requires an explicit forgelm approve, recorded with the approver identity (FORGELM_OPERATOR / OS user; not authenticated). Enforcing that approver and trainer differ is the deployer's responsibility.' Remove 'every model promotion is dual-controlled'.

Other findings with the same root cause

These close with the same fix; update them in the same pull request.

  • CR-A10-005 (code, High) — Docs claim the approval gate is 'dual-controlled' and 'enforces trainer != approver', but approver identity is a self-asserted string and nothing compares it
    severity High · reachability documented-opt-in · intent contract-violation · confidence confirmed · independently confirmed · not reproduced (code trace)
    Failure scenario. An auditor relies on 'dual-controlled' and finds a single operator can train, then approve with the same FORGELM_OPERATOR.
    Where. forgelm/cli/subcommands/_approve.py:603 and 613-620 (approve: approver resolved and logged, no comparison), tests/test_human_approval_gate.py:1112-1180 (TestGrantedOperatorApproverFields; it asserts collapse, not a test-gap against the honest docs), site/compliance.html:239, docs/guides/iso_soc2_deployer_guide.md:29 and docs/qms/sop_change_management.md:108 ("dual-controlled")
    Recommended fix. Reword to 'human-approval gate with attributed (self-asserted) approver', or add an optional approver != operator check with tests.

  • DOC-D2B03-001 (docs, Critical) — docs/design/iso27001_soc2_alignment.md: false claim — A.5.3: 'forgelm approve requires ≠ trainer operator-id'; A.8.2: 'approval gate requires explicit non-trainer operator'; CC1.2: 'Approval gate o…
    severity Critical
    Where. docs/design/iso27001_soc2_alignment.md:155,233,293,545-546 · type: false claim
    The document says. A.5.3: 'forgelm approve requires ≠ trainer operator-id'; A.8.2: 'approval gate requires explicit non-trainer operator'; CC1.2: 'Approval gate operator ≠ trainer'; §8.2: 'trainer ≠ approver enforced by forgelm approve'.
    What the code does. forgelm approve never compares the approver or operator with the trainer's identity. docs/qms/access_control.md §6 states 'ForgeLM does not enforce that the two identities differ'. The A.5.3 row's own note column ('doesn't enforce IdP-level separation') contradicts its evidence column.
    Code references. forgelm/cli/subcommands/_approve.py:512-629, forgelm/cli/subcommands/_approve.py:121-182, docs/qms/access_control.md:177-200
    Proposed correction. Preferred: implement the check in forgelm approve (refuse, or require an audited override, when the approver identity equals the operator on the run's training.started / human_approval.required event). Otherwise rewrite each row as: "human_approval.* events record trainer and approver identities; ForgeLM does not enforce that they differ (…

  • DOC-D2B03-002 (docs, Critical) — docs/guides/iso_soc2_deployer_guide.md: false claim — 'Every model promotion is dual-controlled and forensically attributed.'
    severity Critical
    Where. docs/guides/iso_soc2_deployer_guide.md:28-29 (Turkish mirror: docs/guides/iso_soc2_deployer_guide-tr.md:29-30) · type: false claim
    The document says. 'Every model promotion is dual-controlled and forensically attributed.'
    What the code does. forgelm approve checks the staging path and the required event, then promotes. It never compares the approver/operator identity with the identity that trained the run, so the same identity can train and approve. The project's own QMS doc says 'ForgeLM does not enforce that the two identities differ'. Promotions are attributed (operator plus approver fields), not dual-controlled.
    Code references. forgelm/cli/subcommands/_approve.py:512-629, forgelm/cli/subcommands/_approve.py:151-182, docs/qms/access_control.md:177-200
    Proposed correction. Preferred: fix the code so that forgelm approve compares the resolved approver/operator with the operator on the run's training.started / human_approval.required event and refuses (or requires an audited override) when they match. Interim doc text: "Every model promotion is recorded with the approving identity (operator, approver). Forge…
    Turkish mirror. the Turkish page has the same error; fix both in the same PR

  • DOC-D4B08-001 (docs, Critical) — site/compliance.html: false claim — forgelm approve / reject + forgelm approvals drive the dual-controlled sign-off ... every model promotion is dual-controlled and forensically attributed.
    severity Critical
    Where. site/compliance.html:177, site/compliance.html:239; site/js/translations.js:3863, 3880 · type: false claim
    The document says. forgelm approve / reject + forgelm approvals drive the dual-controlled sign-off ... every model promotion is dual-controlled and forensically attributed.
    What the code does. The approval gate is opt-in (evaluation.require_human_approval defaults to False, forgelm/config.py:1220-1223), so by default no promotion is gated at all. When the gate is on, the approver identity is just the unauthenticated FORGELM_OPERATOR value or the getpass username (forgelm/cli/subcommands/_approve.py:121-170, 603). No check makes the approver differ from the trainer, so one person can tr…
    Code references. forgelm/config.py:1220-1223, forgelm/cli/subcommands/_approve.py:121-170, forgelm/cli/subcommands/_approve.py:587-620
    Proposed correction. Reword: 'Optional (opt-in) staging gate: when evaluation.require_human_approval: true, promotion requires an explicit forgelm approve, recorded with the approver identity (FORGELM_OPERATOR / OS user; not authenticated). Enforcing that approver and trainer differ is the deployer's responsibility.' Remove 'every model promotion is dual-controlled'.

  • DOC-D4B09-001 (docs, Critical) — site/js/translations.js: false claim — forgelm approve/reject drive a 'dual-controlled sign-off'; 'every model promotion is dual-controlled and forensically attributed'
    severity Critical
    Where. site/js/translations.js:3863 (compliance.art14.body), :3880 (compliance.iso.change.body) · type: false claim
    The document says. forgelm approve/reject drive a 'dual-controlled sign-off'; 'every model promotion is dual-controlled and forensically attributed'
    What the code does. ForgeLM does not enforce segregation of duties and does not authenticate the approver. The approver is the string in FORGELM_OPERATOR or getpass.getuser() (forgelm/cli/subcommands/_approve.py:121-175). The project's own guide says it neither verifies the reviewer is human nor enforces that trainer and approver differ (docs/guides/human_approval_gate.md:24-25). The same person who trained can run…
    Code references. forgelm/cli/subcommands/_approve.py:121-175, docs/guides/human_approval_gate.md:24-25
    Proposed correction. Replace with: 'forgelm approve / reject record the approver identity (taken from FORGELM_OPERATOR or the OS user) and an optional comment in the audit log. ForgeLM does not authenticate the approver or enforce that the approver differs from the trainer; enforce that with your IdP and process.' Replace 'dual-controlled and forensically attributed'…

Acceptance criteria

  • A regression test reproduces the failure scenario and asserts the corrected behaviour.
  • Documentation listed above is corrected in English and in its Turkish mirror in the same PR.
  • Every finding in this issue is resolved or explicitly closed with a reason.
  • The release note names the contract this fix restores.

Found by the October 2026 ForgeLM code and documentation review against commit cab2947. Code links point at that commit; line numbers may have moved since. Finding IDs (CR-…, DOC-…, TECH-…) are stable references for this backlog.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: configCode area: configarea: gdpr-approvalCode area: gdpr-approvalbugSomething isn't workingdocumentationImprovements or additions to documentationseverity: criticalBreaks a stated security or safety contractsource: review-2026-10Found by the October 2026 code and documentation reviewwave: 0Roadmap wave 0: immediate (patch release)

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions