Manifest schema
This page describes the current app-side manifest validation surfaces.
The on-disk JSON Schema at
apps/desktop/src/data/osc-manifest-schema.json
drives Monaco/editor validation for the form-supported Windows resource
types. Registration also runs the core shape validator in
packages/core/src/platform.ts. The targeted oscfg version is tracked
separately in packages/core/src/oscfg/registered-types.ts.
Top-level grammar
resources: # REQUIRED - top-level ARRAY
- name: <string> # required by core registration for top-level resources; optional in the editor JSON Schema
type: <string> # REQUIRED, fully-qualified, slash-notation
properties: { ... } # required by the editor JSON Schema for modeled resource items; optional at core shape-validation level
Note:
resources:must be an array of objects. A bare object, a string, or a non-existent key all produce a status-400 hard block at register time. Core registration requires each top-level resource to havenameandtype; nested Group resources can inherit identity from the parent.properties, when present, must be an object. The editor JSON Schema requirestypeandpropertiesfor the resource items it models.
Reserved property keys
The following keys are special - interpreted by the CLI rather than passed through to the resource:
| Key | Used by | Purpose |
|---|---|---|
expression | Microsoft.OSConfig/Test | Compliance assertion expression. |
compliance | Microsoft.OSConfig/Test | One of equal, gte, lte, … |
template | Microsoft.OSConfig/Test | Optional message template. |
resource | Microsoft.OSConfig/Test | The resource the test asserts on. |
Resource wrappers
Microsoft.OSConfig/Group and Microsoft.OSConfig/Test are
wrappers - they nest other resources:
resources:
- name: ssh-hardening
type: Microsoft.OSConfig/Group
properties:
resources: # ← nested array
- name: PermitRootLogin
type: Microsoft.OSConfig/Test
properties:
resource:
type: Microsoft.OSConfig/FileLine
properties:
path: /etc/ssh/sshd_config
line: PermitRootLogin no
expression: "PermitRootLogin == 'no'"
compliance: equal
The core validator walks both wrappers recursively. A 'mixed'
platform manifest is detected even when the offending type is
buried inside a wrapper.
Registry resource
The most-used Windows resource. All three of keyPath,
valueName, and valueType are required at the schema level - see
the required: ["keyPath","valueName","valueType"] line in the
shipped JSON Schema's registry definition. The value shape is
constrained by valueType via a oneOf:
resources:
- name: NTLMOutgoingHardening
type: Microsoft.Windows/Registry
properties:
keyPath: HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0
valueName: NtlmMinClientSec
valueType: REG_DWORD
value: 537395200
Canonical valueType values and matching value shapes
Registry valueType behavior:
- Upstream contract: The current microsoft/osconfig
schema/.document.jsondefines onlyREG_DWORDandREG_QWORDin its integer enum andREG_MULTI_SZin its array enum. - Published examples: Upstream
docs/resources/windows/Registry.md,examples/registry.osc.yaml, and Microsoft Learn set/test/quickstart files useREG_*names. - Compatibility inputs: The editor accepts aliases such as
DwordandStringwhen opening older content. - Execution boundary: ConfigForge normalizes every known alias to
REG_*. - Provider behavior: Observed provider versions can return success for a compatibility alias without applying the registry value.
The canonical pairing rules are:
valueType | value JSON type |
|---|---|
REG_SZ, REG_EXPAND_SZ, REG_BINARY | string |
REG_DWORD, REG_QWORD | integer |
REG_MULTI_SZ | array of string |
ConfigForge maps compatibility aliases before execution:
| Compatibility input | Canonical output |
|---|---|
String | REG_SZ |
ExpandString | REG_EXPAND_SZ |
Binary | REG_BINARY |
Dword, REG_DWORD_LITTLE_ENDIAN | REG_DWORD |
QWord, REG_QWORD_LITTLE_ENDIAN | REG_QWORD |
MultiString | REG_MULTI_SZ |
None | REG_NONE |
REG_DWORD_BIG_ENDIAN is not rewritten because changing its byte order would
change the requested Registry semantics. It remains unchanged so the installed
OSConfig provider can reject it explicitly if unsupported.
A value whose type doesn't match the valueType category will
fail the editor JSON-Schema oneOf constraint. The core register
validator is intentionally lighter and only enforces manifest shape.
The CSV / security-definition import (
packages/core/src/handlers/import.ts) callsinferRegistryValueType(expectedValue)to satisfy thevalueTyperequirement automatically. Integers in the DWORD range becomeREG_DWORD. Larger exact integers becomeREG_QWORD. Other values becomeREG_SZ. New import sources should re-use that helper.
Microsoft.OSConfig/BaselineRule placeholder (v0.2.2+)
Emitted by the importer when the source is an Azure Policy Guest Configuration baseline catalog (a JSON with a settingsReference[] array). Each entry maps to one of these placeholders carrying the rule identity (ruleId, displayName, severity, schemaType, originalSettingName) without the implementation. The OSConfig agent on the target machine is the only thing that knows how to evaluate each rule by its ruleId.
resources:
- name: 1_1_1_1_Ensure_cramfs_kernel_module_is_not_available
type: Microsoft.OSConfig/BaselineRule
properties:
ruleId: 2b568469-ea61-c184-66ba-db6720414ddd
displayName: 1.1.1.1 Ensure cramfs kernel module is not available
severity: Critical
schemaType: string
This type is intentionally not in the editor's schema validator's oneOf - the validator flags it as an unknown type so users see the constraint immediately. The oscfg CLI also doesn't recognise it, so audit/deploy fails loudly. The Azure Policy export refuses any manifest containing this type (would silently report Compliant for every VM otherwise). Map each placeholder to a concrete resource type (Microsoft.Windows/Registry, Microsoft.OSConfig/FileLine, etc.) with real implementation details before deployment.
CSP resource
resources:
- name: TelemetryAllowed
type: Microsoft.Windows/CSP
properties:
path: ./Vendor/MSFT/Policy/Config/System/AllowTelemetry
type: integer
value: 0
properties.path is either a string or { get, set } object pair
(see the csp definition in the schema). properties.type is one
of string / integer / boolean / array. properties.name is
optional.
Audit policy resource
resources:
- name: AuditLogonEvents
type: Microsoft.Windows/AuditPolicy
properties:
subcategory: "Logon"
value: 3 # 0=none, 1=success, 2=failure, 3=success+failure
Microsoft.Windows/AuditPolicy is in the current registered-type
whitelist. Earlier preview builds returned Unsupported resource type
for it; ConfigForge surfaced that as a soft warning at register time.
If you target an older CLI version, that soft-warning path still
triggers - see Reference → Registered types.
Validation
Validation is split across two layers:
| Check | Where | What it does |
|---|---|---|
validateManifestSchema() | packages/core/src/platform.ts | Top-level object, required resources array, resource object/name/type checks, optional properties object check, recursive Group/Test traversal. Hard errors → status 400. |
detectManifestPlatform() | packages/core/src/platform.ts | Classifies into windows / linux / cross-platform / mixed. |
hasMixedPlatformResources() | packages/core/src/platform.ts | Independent mixed-platform detector (catches mixes buried in wrappers). |
isRegisteredType(t, platform) | packages/core/src/oscfg/registered-types.ts | Whitelist lookup. Types missing from the whitelist soft-warn at register time when the manifest targets this host. |
| Editor inline validator | apps/desktop/src/components/manifest-editor.tsx | The tighter Monaco-side validator: enforces e.g. keyPath + valueName + valueType on Registry resources for early UX feedback. |
| Editor JSON-Schema validator | Monaco JSON language service against apps/desktop/src/data/osc-manifest-schema.json | The structural pass for schema-modeled resources. |
Verified bounds
The code currently exposes these verified app-side bounds:
| Bound | Default |
|---|---|
| Max Group/Test traversal depth in core validation | 50 |
| Max IPC manifest/import content payload | 10 MB (MAX_MANIFEST_CONTENT_LEN / MAX_IMPORT_BYTES, CF-SEC-003) |
No separate max-resource-count or per-field string bound is documented here because the current core validator does not expose one.