Framework for OSCAL Risk & Governance Execution
FORGE is a high-performance Rust CLI designed for the Agent-Native software era. It bridges the gap between human-written security policies and autonomous execution by converting Markdown governance into OSCAL (Open Security Controls Assessment Language)—the industry standard for machine-readable compliance.
Natural-language policy can be ambiguous to automation. FORGE converts explicit source documents into schema-validated OSCAL artifacts for later review and tooling.
Whether these artifacts reduce agent mistakes or improve enforcement requires separate measured evaluation; conversion alone does not establish those outcomes.
- High-Fidelity Machine Readability
FORGE ingest human-centric Markdown and produces structured OSCAL Catalogs and Component Definitions.
Machine-Readable Contracts: Explicit schemas give agents a bounded structure to consume. Agent accuracy and token-size benefits remain evaluation hypotheses.
Requirement Atomization: Automatically splits compound "Must X and Must Y" statements into individual, addressable controls.
- Deterministic Agentic Guardrails
FORGE supplies structured policy data for separately configured agent workflows:
Content-Derived Identifiers: UUID v5 tags repeat for the same normalized requirement text. Substantive text or duplicate-occurrence changes can change them; these tags establish no compliance state or approval.
Traceability: Mapped controls carry source links for review against the original policy; a link does not establish security intent or effectiveness.
- Machine-Readable Interoperability
FORGE acts as a translation layer for the modern security stack. It enables the transition from "Policy-as-Prose" to Policy-as-Code:
Downstream Tooling: Machine-readable outputs can be consumed by separately configured tooling. Compatibility with a particular OPA, GitHub Advanced Security or scanner workflow requires its own adapter and qualification.
MCP local queries: Seven read-only MCP tools retrieve recorded governance data through an explicitly selected, reviewed disclosure scope.
- Markdown to OSCAL — Convert policy documents into OSCAL Catalogs or Component Definitions
- Multi-format output — JSON, XML and YAML for Catalog and Component Definition models; JSON/YAML export preserves the complete decoded JSON-compatible tree, while XML and typed helpers retain a model projection
- Schema validation — Validate supported OSCAL v1.2.0–v1.2.3 declarations against the pinned v1.2.3 JSON schemas with semantic checks
- Format conversion — Export supported Catalog and Component Definition artifacts between JSON, XML and YAML
- Requirement atomization — Automatically split compound policy statements into individual controls
- Deterministic IDs — UUID v5 tags repeat for the same normalized requirement text; substantive changes can change them
- Citation extraction — URLs and references extracted into OSCAL back-matter resources
- Traceability — Source-to-OSCAL element mapping embedded as provenance metadata
- Evidence linkage — Deterministic requirement-to-implementation indexes, evidence freshness and baseline checks, plus Catalog/Component JSON overlays preserving original document values
- Reusable policy components — Compose local, hash-pinned Markdown clauses with bounded typed values and span-level provenance
- Offline conversion and validation — The local workspace uses an explicitly launched loopback transport; configured external tools have separate boundaries
See Reusable Policy Components for the closed component/composition contracts, safe substitution rules, impact report, and OSCAL trace provenance workflow.
See Suggestion Evaluation Artifact Preflight for local pinned-artifact checks and complete case accounting. This preparation step leaves authentic evaluation, generation and acceptance gates open.
# Install (requires Rust 1.93.0+)
git clone https://github.com/policy-forge/forge.git
cd forge
cargo build --release
# Convert a policy to an OSCAL Catalog (JSON)
./target/release/forge convert tests/fixtures/sample_policy.md --strategy catalog --format json --output catalog.json
# Validate the generated artifact
./target/release/forge validate catalog.jsonFor Component Definition output, first supply an actual OSCAL Profile using
--source-profile; see the Component workflow.
Convert a Markdown policy document into an OSCAL artifact.
# OSCAL Catalog (groups, controls, statements)
forge convert policy.md --strategy catalog --format json
# OSCAL Component Definition (--source-profile required)
forge convert policy.md --strategy component --source-profile baseline.json --format json
# Output as XML or YAML
forge convert policy.md --strategy catalog --format xml
forge convert policy.md --strategy catalog --format yaml
# Write to a file instead of stdout
forge convert policy.md --strategy catalog --format json --output catalog.json
# Override max input file size (default: 10 MB)
forge convert large-policy.md --strategy catalog --format json --max-size 20Convert a supported Catalog or Component Definition between JSON, XML and YAML. The input format is detected from its extension. JSON/YAML inputs exported to JSON/YAML are validated and emitted as the complete decoded JSON-compatible tree, preserving supported native fields and array order. XML input/output and direct typed helper APIs retain a partial model projection. Retain the original for XML work, original bytes and YAML presentation. Other OSCAL models are not supported by export. See the bounded prerequisite scope, including the exact i64/u64 numeric range and refusal of all floating representations such as 1.0/1e0, plus YAML limits.
# JSON to XML
forge export catalog.json --format xml
# XML to YAML
forge export catalog.xml --format yaml
# YAML to JSON, written to a file
forge export catalog.yaml --format json --output catalog.jsonValidate an OSCAL artifact against FORGE's pinned OSCAL v1.2.3 JSON schema. Auto-detection selects Catalog, Component Definition, Profile, System Security Plan, Control Mapping, or POA&M from the document root; metadata.oscal-version is reported but never selects or downloads a schema.
The explicit --schema-type override supports Catalog, Component Definition, System Security Plan, Control Mapping, and POA&M; Profile documents currently require auto-detection.
# Validate with human-readable output
forge validate catalog.json
# Machine-parseable JSON output
forge validate catalog.json --format json
# Override auto-detected model type
forge validate artifact.json --schema-type catalog
# Validate an OSCAL Control Mapping artifact
forge validate mapping.json --schema-type mapping
# Validate an OSCAL System Security Plan artifact
forge validate ssp.json --schema-type system-security-planNewly generated Catalog, Component Definition, Profile, Assessment Plan, and
SSP artifacts declare OSCAL 1.2.3. Existing Catalog, Component Definition,
and Profile inputs declaring 1.2.0, 1.2.1, 1.2.2, or 1.2.3 remain
supported when they satisfy the v1.2.3 compatibility schema. Export preserves
both metadata.version and the imported metadata.oscal-version; it does not
silently upgrade declarations. Validation, export, and built-in compatibility
checks are offline and use only vendored schemas.
Optional oscal-cli round trips are interoperability evidence, not v1.2.3 schema certification. In particular, oscal-cli v1.0.3 documents an OSCAL v1.1.2 model baseline, so FORGE labels its results advisory. See OSCAL compatibility and schema upgrades.
Compare committed and newly generated OSCAL JSON without printing policy
content. The versioned comparison ignores only FORGE's volatile root uuid and
metadata.last-modified; every other field remains significant.
# Human-readable status
forge drift committed/catalog.json staged/catalog.json
# Machine-readable status for CI
forge drift committed/catalog.json staged/catalog.json --format jsonExit codes are 0 for clean, 1 for drift, and 2 for invalid, unsupported,
or mismatched inputs. Run forge validate on generated artifacts before drift
comparison in enforcement workflows.
Publish explicit, human-reviewed Catalog/Profile relationships as OSCAL v1.2.3 Control Mapping JSON. FORGE validates declarations and references; it does not generate relationships or make compliance determinations.
# Create an unapproved manifest scaffold with fingerprints and inventories
forge mapping init --source source.json --target target.json \
--output mapping-manifest.json
# Build Mapping JSON and a separate deterministic review report
forge mapping build --manifest mapping-manifest.json \
--output mapping.json --report mapping-report.json --report-format json
# Check current resources against a prior Mapping baseline
forge mapping check --manifest mapping-manifest.json \
--baseline mapping.json --report-format json --fail-on anyMapping commands are local-file-only and JSON-only. Profiles require an
explicit resolved Catalog companion and reviewer attestation in the manifest.
FORGE preserves but does not authenticate reviewer identity or authority, and
users remain responsible for rights to process framework content. Exit codes are 0 for a
completed build/check with no selected review impact, 1 when a completed
check triggers --fail-on, and 2 when trustworthy analysis is impossible.
Reports default to identifiers, counts, and hashes; --include-excerpts is an
explicit sensitive-output opt-in.
Portable review commands are an unreleased F12 implementation candidate and are not included in the published v1.1.0 binary.
forge review init, respond, merge, status, export-html,
export-notifications and supersede support explicit local re-review of selected
Mapping assertions and applicability decisions. init, merge and status
consume the complete recorded Approved/current closure; recorded exports preserve their
snapshot limits. Supersession links explicit old/new items after complete native
change impact, keeps the old queue historical, and transfers no responses or
quorum. Reviewer keys and times remain asserted; quorum does not promote domain
approval. See the
portable review queue guide for the private inputs,
immutable responses, dissent, disclosure limits and remaining acceptance gates.
The separate Lifecycle review exchange candidate
registers forge review lifecycle init/respond/merge/status with closed /2
documents in the implementation candidate. These instructions apply after that
code and documentation are integrated; published v1.1.0 does not include the
exchange. Recorded review results grant no native Lifecycle transition or
reviewer authority.
The separate Authoring review exchange candidate
adds forge review authoring init/respond/merge/status and closed /3 documents
for one complete current saved forge.authoring-plan/1. Its TEMP candidate has
full-test/strict-lint evidence and a completed compiled CLI campaign; the linked
guide records Rustdoc and physical LLVM scopes. Final integrated checks and
hosted/platform/human acceptance remain open. Review quorum grants no native plan
promotion or authenticated reviewer authority.
Package explicit assessor-authored observations, findings, and risks into schema-valid OSCAL 1.2.3 Assessment Results without inferring compliance or evidence sufficiency:
forge assessment results init --assessment-plan assessment-plan.json \
--ssp ssp.json --profile profile.json --catalog catalog.json \
--output assessment-results-manifest.json
forge assessment results build --manifest assessment-results-manifest.json \
--output assessment-results.json \
--report assessment-results-review.json --report-format jsonThe workflow is offline, deterministic, exact-context-bound, and
content-minimizing. Optional PRD 060 linkage input supplies evidence identity
only. Baseline reports flag stable-object, status, rationale, stale-reference,
and upstream-fingerprint changes with exit 1; invalid analysis exits 2
before writes. Baselines must contain exactly one result epoch; plural baselines
are invalid even with --fail-on never. See
OSCAL Assessment Results.
forge assessment results export-poam turns explicitly selected, caller-reviewed
risks and a complete caller-authored first-plan workflow into forge.poam/1.
Supply every owner, date, milestone and initial history event; then use the
maintained POA&M check/build commands. The caller's review assertion establishes
no reviewer authority or terminal approval. See
reviewed-risk authoring for the exact
request, source checks and remaining acceptance gates.
forge assessment results append-epoch appends one sealed result with explicit
caller-declared risk continuity. It preserves prior results, saves a complete JSON
companion, and can display the same report as JSON, text or static HTML. See
sealed assessment epochs for the same-context
profile, explicit source rebinding and independent publication semantics.
Create an unselected forge.poam/1 scaffold from one explicitly identified
Assessment Results result and its exact local companions. Then check only the
source integrity boundary:
forge poam check --manifest ./assessment-bundle/poam.json \
--source-only --format jsonThe inventory includes every finding and risk in that result, including satisfied
findings and closed risks. It does not validate remediation ownership, schedule,
review or closure. Separate authored poam check --workflow --as-of YYYY-MM-DD
and poam build commands validate nonterminal ownership/history/schedules and
generate native JSON from exact source selections. Completion and risk acceptance
remain refused pending the recorded closure decision. poam baseline reports
complete prior/current identity and field changes against the current source
capture, including refused revisions, without creating a native artifact. See
baseline comparison and the
authored command guide. Remaining F08 features and
acceptance remain open.
See POA&M source foundation for explicit scaffold
inputs, limits, supported source profile and remaining gates.
forge poam portfolio combines 1–32 explicitly paired native POA&M and authoring
plans into complete JSON and optional static HTML reports. Supply an explicit date
and existing output directory; source references retain their original bundle base.
See portfolio reports for pairing, counts and safe outputs.
forge poam outbound prepares a minimized local change set from one explicit
current native/authoring pair and item-intent selection. It rechecks the eight
original files before output; a valid handoff exits 0 and grants no remote action.
See local outbound change sets for inputs, schema,
privacy, safe publication and remaining connector gates.
forge poam evidence inspects every declared closure-evidence assertion against explicit linkage bindings and current local bytes, while keeping terminal admission and evidence approval separate. See local evidence inspection for path bases, reports and review conditions.
Bind a policy version's declared review state to exact local source and generated OSCAL bytes. Lifecycle history is append-only and deterministic; FORGE preserves declared actors and roles but does not authenticate identity or authority.
These native Lifecycle commands remain separate from the candidate portable Lifecycle re-review exchange.
# Create a draft record with a date-only review schedule
forge lifecycle init --source policy.md --artifact catalog.json \
--output policy-lifecycle.json --policy-key access-control \
--version-key v1 --title "Access Control Policy" --owner alice \
--party alice=owner,author --party bob=reviewer --party carol=approver \
--next-review 2027-08-25 --separate-reviewer-approver
# Non-destructively migrate a legacy /1 history before mutation or attestation
forge lifecycle migrate --record policy-lifecycle-v1.json \
--output policy-lifecycle-v2.json
# Append reviewed transitions with explicit event times
forge lifecycle transition --record policy-lifecycle.json --to in-review \
--actor bob --role reviewer --at 2026-08-25T17:00:00Z \
--rationale "Review completed" --apply
forge lifecycle transition --record policy-lifecycle.json --to approved \
--actor carol --role approver --at 2026-08-25T18:00:00Z \
--rationale "Approved for publication" --apply
# Deterministic CI status; exit 1 means lifecycle action is required
forge lifecycle status --record policy-lifecycle.json \
--as-of 2026-08-25 --format json
# Group an explicit portfolio by owner and next-review date
forge lifecycle queue --record policy-lifecycle.json \
--as-of 2026-08-25 --format json
# Export deterministic unsigned approval evidence; refuses drifted approvals
forge lifecycle attest --record policy-lifecycle.json \
--output approval-attestation.jsonlifecycle check validates one record or an explicitly supplied portfolio,
including supersession links and cycles, without deriving date-relative review
conditions. New records use context-bound forge.policy-lifecycle/2 event IDs;
legacy /1 histories remain readable and have an explicit migrate command.
JSON check/status output is always an array, including for one
record. status never emits policy prose by default. Re-review transitions can
link bounded PRD-057 findings with repeatable --impact-finding-id values.
due-soon is informational under the publication gate; overdue, drifted,
artifact-identity-changed, and non-approved states require action. Exit codes
are 0 for a valid record under the selected gate, 1 for a valid
action-required result, and 2 for an invalid record or transition.
Record explicit human scope decisions against an exact Catalog/Profile revision, then combine them with reviewed Control Mapping artifacts. FORGE reports mapping participation and review state; it does not infer scope or make assurance claims.
# Inventory every control; omitted decisions classify as under-review
forge applicability init --framework framework.json \
--output applicability.json
# Produce a deterministic JSON report and gate on applicable unmapped controls
forge applicability analyze --manifest applicability.json \
--format json --output applicability-report.json \
--fail-on applicable-unmapped
# Filter displayed details without changing framework-wide totals
forge applicability analyze --manifest applicability.json --format html \
--group access-control --state applicable-unmapped \
--output applicability-report.html
# Deterministically gate overdue deferrals (no wall-clock dependency)
forge applicability analyze --manifest applicability.json \
--fail-on overdue-deferred --as-of 2026-10-01Profiles require --resolved-catalog during initialization and explicit
resolved_catalog_attestation: true before analysis. Reports include exact
framework, policy-source, and Mapping fingerprints and provenance, reconciled
category totals, and a stable machine-readable review queue. Exit codes are 0 for a valid analysis
whose selected gate does not fire, 1 for a valid report requiring review, and
2 when trustworthy analysis is impossible.
Statement-level Mapping Collection relationships remain distinct statement
evidence and never roll up implicitly to a parent control classification. The
overdue deferral gate fires only when revisit_date is strictly earlier than
--as-of; a deferral is due, but not yet overdue, on its revisit date.
Compare an exact old/new OSCAL Catalog pair or attested Profile-plus-resolved-Catalog pair and trace changed or removed controls through optional PRD 055 Mapping Collections and a PRD 056 applicability manifest:
forge framework impact --manifest framework-impact.json \
--format json --output framework-impact-report.jsonThe closed forge.framework-impact/1 manifest declares both resources' paths,
SHA-256 fingerprints, root UUIDs, document and OSCAL versions, Profile companion
evidence when applicable, each local Mapping Collection and its framework role,
and optionally the authoritative forge.applicability/1 manifest. Applicability
analysis must match the old baseline and the complete target-side Mapping
portfolio exactly. Reports retain prior gap state, decision owner, policy sources,
stable finding IDs, priorities, required actions, and dependency paths without
framework prose. Reviewer-authored forge.successor-map/1 declarations preserve
approved successor, split, and merge evidence without inferring continuity.
Report-bound forge.framework-impact-dispositions/1 records retain resolved,
accepted-risk, and still-open review state while leaving raw findings visible.
A PRD 057 finding ID can also be attached to a PRD 058 transition with
lifecycle transition --impact-finding-id. Text, JSON, Markdown, static HTML,
and GitHub workflow-command output share the same report model. Exact-match
filters can narrow displayed findings by framework group, prior applicability
decision state, policy source, impact priority, or owner. Filters combine with
AND semantics and never weaken full summary totals or CI gate evaluation. The
default gate exits 1 for open blocking or review-required findings and 2
when complete trustworthy analysis is impossible.
Analyze policy-requirement identity changes and optionally apply explicit reviewer declarations:
forge migrate old-policy.md new-policy.md --format json \
--successor-map successor-map.jsonThe closed forge.successor-map/1 contract supports one-to-one successors,
one-to-many splits, and many-to-one merges with reviewer, timestamp, and
rationale evidence. FORGE validates and preserves declarations but does not
authenticate the reviewer or mutate either policy.
# Verbose: show pipeline stage information on stderr
forge -v convert policy.md --strategy catalog --format json
# Quiet: suppress all non-essential output
forge -q convert policy.md --strategy catalog --format jsonCheck in a .forge.toml to make repository command defaults reviewable and reusable:
schema-version = 1
[convert]
strategy = "catalog"
format = "json"
output = "generated/oscal"
jobs = 0
summary = false
[validate]
format = "text"
timeout-seconds = 30# Explicit inputs only — strategy/format/output come from the project file
forge convert policies/policy-a.md policies/policy-b.md
# Validate the configuration without side effects
forge config checkPrecedence per setting: explicit CLI > $FORGE_JOBS environment override > project config > built-in default.
See Project Configuration for the full schema,
path rules, and selection order (--config > $FORGE_CONFIG > discovery).
Note: a checked-in config makes option resolution deterministic; generated OSCAL artifacts still embed runtime UUID/timestamp metadata and are not yet byte-reproducible.
cargo install forgeDownload the latest release for your platform from GitHub Releases:
| Platform | Architecture | Archive |
|---|---|---|
| Linux | x86_64 | forge-*-x86_64-unknown-linux-gnu.tar.gz |
| macOS | x86_64 (Intel) | forge-*-x86_64-apple-darwin.tar.gz |
| macOS | aarch64 (Apple Silicon) | forge-*-aarch64-apple-darwin.tar.gz |
| Windows | x86_64 | forge-*-x86_64-pc-windows-msvc.zip |
Select a published tag and the matching Rust target from the table above.
Replace vX.Y.Z before running these download-only examples; it is a placeholder,
not a claim that a release exists. Archive names include both the tag and target.
Linux / macOS:
forge_tag=vX.Y.Z
forge_target=x86_64-unknown-linux-gnu # choose the target for your platform
forge_archive="forge-${forge_tag}-${forge_target}.tar.gz"
curl -fsSL "https://github.com/policy-forge/forge/releases/download/${forge_tag}/${forge_archive}" -o "$forge_archive"Windows (PowerShell):
$forgeTag = 'vX.Y.Z'
$forgeArchive = "forge-$forgeTag-x86_64-pc-windows-msvc.zip"
Invoke-WebRequest -Uri "https://github.com/policy-forge/forge/releases/download/$forgeTag/$forgeArchive" -OutFile $forgeArchiveVerify the selected release's published SHA-256 checksum and provenance before extracting or installing its archive.
The release workflow is configured to publish SHA-256 checksums and SLSA provenance. Check the evidence attached to the selected published tag for the archive hashes and any verified SLSA level.
git clone https://github.com/policy-forge/forge.git
cd forge
cargo build --releaseFORGE accepts Markdown files (.md / .markdown) with optional YAML frontmatter:
---
title: "Access Control Policy"
version: "2.0"
author: "Security Team"
date: "2026-01-15"
---
# Access Control
All users must authenticate before accessing systems.
## Authentication Requirements
- Users must use multi-factor authentication
- Passwords must be at least 12 characters
- Sessions must timeout after 30 minutes of inactivity
## Authorization
- Access must follow principle of least privilege
- Role-based access control must be enforcedHeadings become OSCAL groups and controls. List items, tables, and paragraphs become control statements. Compound requirements like "Systems must X and must Y" are automatically split into atomic statements.
PDF (.pdf) and DOCX (.docx) documents are also accepted directly — headings and list styles are mapped to the same document model as Markdown. Plain-text formats can be pre-converted with pandoc or markitdown if needed.
25 sample policies are included in example_data/ covering topics from acceptable use to incident response.
The release workflow is configured to publish SHA-256 checksums and SLSA provenance. Check the evidence attached to the selected published tag for the archive hashes and any verified SLSA level.
Conversion ingests and reconstructs the source, extracts sections and clauses, assembles and atomizes the internal document, assigns stable IDs, then enriches citations, modalities and parameters. Model mapping is followed by structural and semantic validation before final requested-format serialization. See the architecture guide for the model-specific paths.
These checks validate supported OSCAL structure and references. Review the generated requirements against the source policy; validity alone does not establish security intent, implementation or effectiveness.
FORGE is on the v1.1.0 release line. The original 50-item roadmap is complete:
- Phase 1 — Foundation: Markdown-to-OSCAL Catalog and Component Definition pipeline, deterministic UUIDs, traceability, validation, golden files, error handling, and benchmarks.
- Phase 2 — Control Layer & Multi-Format: JSON/XML/YAML output, round-trip checks, export subcommand, Profile generation, parameter tailoring, modality tagging, and parameter extraction.
- Phase 3 — Ecosystem & Community: oscal-cli integration, trace reports, diff reports, batch conversion, summary dashboards, Assessment Plan scaffolding, SSP templates, community examples, documentation, cross-platform CI, and release automation.
Post-v1.1.0 work is tracked separately from the completed WI-1–WI-50 history. Assessment Results workflows and the unreleased local web/API workspace are implemented technical tranches with remaining product, human and release gates. Full POA&M, built-in Profile Resolution, GRC integrations and other roadmap scope remain separate; implementation or tests do not establish PRD acceptance.
See docs/FORGE_PRODUCT_ROADMAP.md for the reconciled roadmap.
FORGE is built for the community. We welcome PRs for new language bindings, MCP adapters, and enhanced semantic validators.
# Run the same checks used by CI
./scripts/ci-local.sh
# Install local git pre-commit hook
./scripts/install-hooks.shYou can bypass the local hook once with:
SKIP_FORGE_PRECOMMIT=1 git commit -m "your message"And enable stricter hook checks (bench + audit + deny) with:
FORGE_PRECOMMIT_STRICT=1 git commit -m "your message"Policy Forge: Forging the rules that power the agents.
forge workspace --project <directory> opens the local web review surface.
Use --read-only to inspect registered files without project writes, or
--machine-session for the documented headless API. This is an unreleased
draft implementation: security, accessibility and pilot gates are still open,
and it is not part of a release. See the
local workspace guide for unlock, explicit registration,
review, preview/commit, recovery, API contracts, bounds, and remaining release gates.
The 2026-10-03 documentation snapshot
retains its historical committed/working-tree distinction. The historical captured
F12 c2fa4cd source declares API1 1.2.0/39 and API2 2.4.0/65 operations. Exact-tree
hosted API, Chrome and staged-source development workflows have successful scoped
receipts; the same hosted run retains dependency-audit and headless failures.
These results do not complete F04, platform/network-denial, human or release gates.
These API versions are not product releases. Separate drafts, local checks and hosted
checkpoints do not establish full Must/Should, platform, human or release
acceptance.
MIT
