From 585871e874ede9f0772b3cfc71edc8f2715df2e4 Mon Sep 17 00:00:00 2001 From: oxmc7769 Date: Mon, 20 Apr 2026 09:09:50 -0700 Subject: [PATCH] Initial commit --- README.md | 94 +++ .../dh_installchangelogs.dch.trimmed | 8 + .../installed-by-dh_installdocs | 0 debian/changelog | 8 + debian/control | 29 + debian/debhelper-build-stamp | 1 + debian/files | 2 + debian/rules | 10 + debian/source/format | 1 + debian/vesperprofiled-config-schema.substvars | 2 + .../DEBIAN/control | 25 + .../DEBIAN/md5sums | 2 + .../changelog.Debian.gz | Bin 0 -> 274 bytes .../vesperprofiled/schema/profile.schema.yml | 535 ++++++++++++++++++ schema/profile.schema.yml | 535 ++++++++++++++++++ 15 files changed, 1252 insertions(+) create mode 100644 README.md create mode 100644 debian/.debhelper/generated/vesperprofiled-config-schema/dh_installchangelogs.dch.trimmed create mode 100644 debian/.debhelper/generated/vesperprofiled-config-schema/installed-by-dh_installdocs create mode 100644 debian/changelog create mode 100644 debian/control create mode 100644 debian/debhelper-build-stamp create mode 100644 debian/files create mode 100755 debian/rules create mode 100644 debian/source/format create mode 100644 debian/vesperprofiled-config-schema.substvars create mode 100644 debian/vesperprofiled-config-schema/DEBIAN/control create mode 100644 debian/vesperprofiled-config-schema/DEBIAN/md5sums create mode 100644 debian/vesperprofiled-config-schema/usr/share/doc/vesperprofiled-config-schema/changelog.Debian.gz create mode 100644 debian/vesperprofiled-config-schema/usr/share/vesperprofiled/schema/profile.schema.yml create mode 100644 schema/profile.schema.yml diff --git a/README.md b/README.md new file mode 100644 index 0000000..99ba9dd --- /dev/null +++ b/README.md @@ -0,0 +1,94 @@ +# vesperprofiled-config-schema + +Schema definitions package for VesperOS configuration profiles. + +Installed at `/usr/share/vesperprofiled/schema/profile.schema.yml`. + +--- + +## What this package does + +`vesperprofiled` reads this schema at startup to determine which payload types and fields are valid for the current installation. Any `.vconfig` profile containing a payload type not listed in `allowed-payload-types` will be **rejected at install time** with a clear error. + +Shipping the schema separately from the daemon means: + +- **Independent updates** — schema additions (new payload types, new optional fields) don't require rebuilding or reflashing the daemon binary. +- **OEM restriction** — OEMs building VesperOS-based products can ship a trimmed schema that only exposes the configuration surface their platform supports. A digital signage OEM might allow only `wifi`, `cert`, `kiosk`, and `mdm`. An enterprise desktop OEM might allow everything except `kiosk` and `asam`. +- **Schema versioning** — the `schema-version` field is checked by the daemon at startup. A newer daemon with an older schema is always fine. An older daemon with a newer schema logs a warning and falls back to its compiled-in defaults. + +--- + +## OEM customisation + +To restrict available payload types, create a replacement Debian package: + +**1. Copy and trim the schema** + +```bash +cp /usr/share/vesperprofiled/schema/profile.schema.yml \ + my-schema/profile.schema.yml + +# Edit my-schema/profile.schema.yml: +# - Remove payload type entries from allowed-payload-types +# - Remove their blocks from the payloads: section +# - Bump schema-version if you consider this a new schema variant +``` + +**2. Create your package** + +`debian/control`: +``` +Package: my-vesperos-config-schema +Architecture: all +Depends: ${misc:Depends} +Provides: vesperprofiled-config-schema +Conflicts: vesperprofiled-config-schema +Replaces: vesperprofiled-config-schema +Description: Trimmed VesperOS profile schema for My Product + Only allows: wifi, cert, mdm, kiosk, passcode, restrictions. +``` + +`debian/rules`: +```makefile +#!/usr/bin/make -f +%: + dh $@ +override_dh_auto_install: + install -Dm 0644 profile.schema.yml \ + debian/my-vesperos-config-schema/usr/share/vesperprofiled/schema/profile.schema.yml +``` + +**3. Add to your product package list** + +```makefile +# In your VesperOS device makefile or product.mk: +PRODUCT_PACKAGES += my-vesperos-config-schema +``` + +Because your package `Provides: vesperprofiled-config-schema` and `Conflicts: vesperprofiled-config-schema`, `apt` will automatically use yours in place of the default when both are available. + +--- + +## Schema versioning + +The `schema-version` field in the YAML file follows `MAJOR.MINOR.PATCH`: + +- **PATCH** — non-breaking: new optional fields added to existing payload types. +- **MINOR** — new payload types added to `allowed-payload-types`. Older daemons that don't know the new type will accept profiles containing it but log a warning and skip the unknown payload. +- **MAJOR** — breaking: required fields renamed, payload types removed, or semantics changed. Daemons older than this MAJOR version must not run with a schema of a higher MAJOR version. + +--- + +## Building the package + +```bash +dpkg-buildpackage -us -uc -b -A # Architecture: all, no signing +``` + +--- + +## Files installed + +``` +/usr/share/vesperprofiled/schema/profile.schema.yml +``` diff --git a/debian/.debhelper/generated/vesperprofiled-config-schema/dh_installchangelogs.dch.trimmed b/debian/.debhelper/generated/vesperprofiled-config-schema/dh_installchangelogs.dch.trimmed new file mode 100644 index 0000000..70990a5 --- /dev/null +++ b/debian/.debhelper/generated/vesperprofiled-config-schema/dh_installchangelogs.dch.trimmed @@ -0,0 +1,8 @@ +vesperprofiled-config-schema (1.0.0-1) trixie; urgency=medium + + * Initial release. Schema version 1.0.0. + * All 55 payload types defined with required/optional field lists. + * Signing requirements, singleton constraints, and allowed-payload-types + list all configurable by OEMs via a replacement package. + + -- oxmc Sun, 19 Apr 2026 00:00:00 +0000 diff --git a/debian/.debhelper/generated/vesperprofiled-config-schema/installed-by-dh_installdocs b/debian/.debhelper/generated/vesperprofiled-config-schema/installed-by-dh_installdocs new file mode 100644 index 0000000..e69de29 diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..70990a5 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,8 @@ +vesperprofiled-config-schema (1.0.0-1) trixie; urgency=medium + + * Initial release. Schema version 1.0.0. + * All 55 payload types defined with required/optional field lists. + * Signing requirements, singleton constraints, and allowed-payload-types + list all configurable by OEMs via a replacement package. + + -- oxmc Sun, 19 Apr 2026 00:00:00 +0000 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..591ae1b --- /dev/null +++ b/debian/control @@ -0,0 +1,29 @@ +Source: vesperprofiled-config-schema +Section: admin +Priority: optional +Maintainer: oxmc +Build-Depends: debhelper-compat (= 13) +Standards-Version: 4.7.0 +Homepage: https://vesperos.oxmc.me +Vcs-Git: https://git.oxmc.me/vesperos/vesperprofiled-config-schema.git + +Package: vesperprofiled-config-schema +Architecture: all +Depends: ${misc:Depends} +Breaks: vesperprofiled (<< 1.0.0) +Description: VesperOS configuration profile schema definitions + Provides the YAML schema file that defines which .vconfig payload types + and fields are valid on this VesperOS installation. vesperprofiled reads + this schema at startup and rejects profiles containing payload types not + listed in it. + . + Shipping the schema as a separate package allows: + - Independent schema updates without rebuilding the daemon binary. + - OEM customisation: replace this package with a trimmed version that + only lists the payload types your platform supports. + - Schema versioning: the daemon checks schema-version compatibility + at startup and refuses to run with an incompatible schema. + . + OEMs: create your own package that Provides: vesperprofiled-config-schema + and contains a customised profile.schema.yml with only the payload types + your build supports. diff --git a/debian/debhelper-build-stamp b/debian/debhelper-build-stamp new file mode 100644 index 0000000..58b85c1 --- /dev/null +++ b/debian/debhelper-build-stamp @@ -0,0 +1 @@ +vesperprofiled-config-schema diff --git a/debian/files b/debian/files new file mode 100644 index 0000000..935879d --- /dev/null +++ b/debian/files @@ -0,0 +1,2 @@ +vesperprofiled-config-schema_1.0.0-1_all.deb admin optional +vesperprofiled-config-schema_1.0.0-1_amd64.buildinfo admin optional diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..61e4ec0 --- /dev/null +++ b/debian/rules @@ -0,0 +1,10 @@ +#!/usr/bin/make -f +%: + dh $@ + +override_dh_auto_build: + # Architecture: all — nothing to compile + +override_dh_auto_install: + install -Dm 0644 schema/profile.schema.yml \ + debian/vesperprofiled-config-schema/usr/share/vesperprofiled/schema/profile.schema.yml diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/debian/vesperprofiled-config-schema.substvars b/debian/vesperprofiled-config-schema.substvars new file mode 100644 index 0000000..978fc8b --- /dev/null +++ b/debian/vesperprofiled-config-schema.substvars @@ -0,0 +1,2 @@ +misc:Depends= +misc:Pre-Depends= diff --git a/debian/vesperprofiled-config-schema/DEBIAN/control b/debian/vesperprofiled-config-schema/DEBIAN/control new file mode 100644 index 0000000..5ca65e4 --- /dev/null +++ b/debian/vesperprofiled-config-schema/DEBIAN/control @@ -0,0 +1,25 @@ +Package: vesperprofiled-config-schema +Version: 1.0.0-1 +Architecture: all +Maintainer: oxmc +Installed-Size: 28 +Breaks: vesperprofiled (<< 1.0.0) +Section: admin +Priority: optional +Homepage: https://vesperos.oxmc.me +Description: VesperOS configuration profile schema definitions + Provides the YAML schema file that defines which .vconfig payload types + and fields are valid on this VesperOS installation. vesperprofiled reads + this schema at startup and rejects profiles containing payload types not + listed in it. + . + Shipping the schema as a separate package allows: + - Independent schema updates without rebuilding the daemon binary. + - OEM customisation: replace this package with a trimmed version that + only lists the payload types your platform supports. + - Schema versioning: the daemon checks schema-version compatibility + at startup and refuses to run with an incompatible schema. + . + OEMs: create your own package that Provides: vesperprofiled-config-schema + and contains a customised profile.schema.yml with only the payload types + your build supports. diff --git a/debian/vesperprofiled-config-schema/DEBIAN/md5sums b/debian/vesperprofiled-config-schema/DEBIAN/md5sums new file mode 100644 index 0000000..cd32634 --- /dev/null +++ b/debian/vesperprofiled-config-schema/DEBIAN/md5sums @@ -0,0 +1,2 @@ +322df8776e639e12f6265a6e6232b229 usr/share/doc/vesperprofiled-config-schema/changelog.Debian.gz +82842e0a3dce5dec15cc6e954cb23ba5 usr/share/vesperprofiled/schema/profile.schema.yml diff --git a/debian/vesperprofiled-config-schema/usr/share/doc/vesperprofiled-config-schema/changelog.Debian.gz b/debian/vesperprofiled-config-schema/usr/share/doc/vesperprofiled-config-schema/changelog.Debian.gz new file mode 100644 index 0000000000000000000000000000000000000000..c3134db5d5c4dc011eba81a2b3c1b2f4d638352c GIT binary patch literal 274 zcmV+t0qy=DiwFP!0000212vD$a>6hSgzr4X9{WSmzzm(Ce^U-U^w8;nClIj`G*xWZ zc7VKnjiDM}w3fcr9yodqKDbVlP1QQvNngcw&jaCRQ8#r{EpCy5oP?h-hMsLZy$)<- z9A-1%4xd(%kRq@$MXs^EY#%s8aTWzqm(h(XRx5a#)R94&JVzMr#InIr(mq3eM+s~m zoKJZ@9rP>CsCAY19J*#3WXV4LC`F-yuR`{fKV1(G6@H6T@Y%;B!KRk6(|6zcgK zm)v8ZoicV4zCXSq4nm-8= schema version (newer daemon, older schema ok). +# +# OEM customisation: +# To restrict available payload types, create a trimmed copy of this file +# and ship it as your own vesperprofiled-config-schema package with a +# custom Provides: field. Remove entire payload blocks for unsupported types. +# The daemon will reject any profile containing an unlisted payload type. +# ============================================================================= + +schema-version: "1.0.0" + +# --------------------------------------------------------------------------- +# Allowed payload types for this schema version. +# Remove entries to restrict what profiles may contain on this platform. +# --------------------------------------------------------------------------- +allowed-payload-types: + - mdm + - scep + - pkcs12 + - cert + - cert-preference + - cert-transparency + - wifi + - ethernet + - vpn + - vpn-per-app + - email + - exchange + - caldav + - calendar-subscription + - carddav + - ldap + - passcode + - restrictions + - kiosk + - asam + - proxy-http + - dns-proxy + - domains + - network-usage-rules + - cellular + - web-filter + - web-clip + - font + - notifications + - sso + - active-directory + - ad-certificate + - time-server + - software-update + - firewall + - privacy + - parental-controls + - removal-password + - identification + - google-account + - home-screen + - desktop + - screensaver + - global-preferences + - shared-device + - education + - airprint + - airplay + - airplay-security + - system-policy + - system-policy-rule + - smartcard + - kernel-extension-policy + - media-management + - full-disk-encryption + - fde-escrow + - first-boot + - setup-assistant # alias for first-boot; always include alongside first-boot + +# --------------------------------------------------------------------------- +# Signing requirements by payload type. +# Payloads listed here REQUIRE a signed (CMS/PKCS#7) profile envelope. +# Unsigned profiles containing any of these types will be rejected. +# --------------------------------------------------------------------------- +signing-required: + - mdm + - removal-password + - kiosk + - asam + +# --------------------------------------------------------------------------- +# Singleton payload types. +# Only one instance of each of these is permitted per profile. +# --------------------------------------------------------------------------- +singletons: + - mdm + - passcode + - restrictions + - kiosk + - asam + - proxy-http + - web-filter + - global-preferences + - shared-device + - parental-controls + - removal-password + - identification + - home-screen + - airplay-security + - system-policy + - first-boot + - setup-assistant + +# --------------------------------------------------------------------------- +# Payload field definitions. +# Each entry documents the fields for one payload type. +# The daemon uses this for validation — unknown fields in a profile +# are logged as warnings but do not block installation. +# Required fields that are missing will block installation. +# --------------------------------------------------------------------------- +payloads: + + # ── Top-level profile fields ───────────────────────────────────────────── + profile: + required: [id, uuid, version] + optional: + version: { type: integer, value: 1 } + id: { type: string, pattern: "reverse-dns" } + uuid: { type: string, pattern: "uuid-v4" } + scope: { type: enum, values: [system, user], default: user } + meta: { type: object } + lifecycle: { type: object } + consent: { type: object } + + lifecycle: + optional: + removal: { type: enum, values: [free, locked, password], default: free } + expires-at: { type: string, pattern: "iso8601" } + expires-after: { type: integer, description: "Seconds from install" } + ota-refresh-after: { type: string, pattern: "iso8601" } + + # ── MDM ────────────────────────────────────────────────────────────────── + mdm: + required: [server-url, identity-cert-uuid, access-rights, push-topic] + optional: + checkin-url: { type: string } + sign-messages: { type: boolean, default: false } + checkout-on-removal: { type: boolean, default: false } + use-development-push: { type: boolean, default: false } + capabilities: { type: array } + + # ── SCEP ───────────────────────────────────────────────────────────────── + scep: + required: [url, challenge] + optional: + instance-name: { type: string } + subject: { type: array } + key: { type: object } + san: { type: object } + ca-fingerprint: { type: string, encoding: base64 } + retries: { type: integer, default: 3 } + retry-delay-seconds: { type: integer, default: 10 } + + # ── Certificates ───────────────────────────────────────────────────────── + pkcs12: + required: [data] + optional: + password: { type: string } + all-apps-access: { type: boolean, default: false } + + cert: + required: [data] + + cert-preference: + required: [name, cert-uuid] + + # ── Wi-Fi ──────────────────────────────────────────────────────────────── + wifi: + required: [ssid] + optional: + hidden: { type: boolean, default: false } + auto-join: { type: boolean, default: true } + security: { type: object } + mac-address-mode: { type: enum, values: [hardware, random], default: hardware } + hotspot: { type: object } + proxy: { type: object } + eap: { type: object } + qos-marking: { type: object } + + # ── Ethernet ───────────────────────────────────────────────────────────── + ethernet: + optional: + interface: { type: string, default: first-active } + eap: { type: object } + + # ── VPN ────────────────────────────────────────────────────────────────── + vpn: + optional: + display-name: { type: string } + full-tunnel: { type: boolean, default: false } + on-demand: { type: object } + ikev2: { type: object } + l2tp: { type: object } + custom: { type: object } + + vpn-per-app: + required: [vpn-uuid] + optional: + app-mappings: { type: array } + browser-domains: { type: array } + + # ── Mail accounts ───────────────────────────────────────────────────────── + email: + required: [account, incoming, outgoing] + optional: + smime: { type: object } + restrictions: { type: object } + + exchange: + required: [server, account] + optional: + sync: { type: object } + smime: { type: object } + restrictions: { type: object } + + caldav: + required: [host, username] + optional: + description: { type: string } + port: { type: integer } + ssl: { type: boolean, default: true } + principal-url: { type: string } + password: { type: string } + use-oauth: { type: boolean, default: false } + + calendar-subscription: + required: [url] + optional: + description: { type: string } + username: { type: string } + password: { type: string } + ssl: { type: boolean, default: true } + + carddav: + required: [host, username] + optional: + description: { type: string } + port: { type: integer } + ssl: { type: boolean, default: true } + principal-url: { type: string } + password: { type: string } + use-oauth: { type: boolean, default: false } + + # ── Directory ───────────────────────────────────────────────────────────── + ldap: + required: [host] + optional: + description: { type: string } + ssl: { type: boolean, default: true } + username: { type: string } + password: { type: string } + search-settings: { type: array } + + # ── Security policies ───────────────────────────────────────────────────── + passcode: + optional: + require: { type: boolean, default: true } + allow-simple: { type: boolean, default: true } + require-alphanumeric: { type: boolean, default: false } + min-length: { type: integer, default: 6 } + min-complex-chars: { type: integer, default: 0 } + expiry: { type: object } + lockout: { type: object } + force-change-at-next-login: { type: boolean, default: false } + custom-regex: { type: object } + + restrictions: + optional: + apps: { type: object } + hardware: { type: object } + network: { type: object } + cloud: { type: object } + browser: { type: object } + content-ratings: { type: object } + sharing: { type: object } + open-in: { type: object } + user: { type: object } + input: { type: object } + + kiosk: + required: [app] + optional: + hardware: { type: object } + accessibility:{ type: object } + + asam: + required: [allowed-apps] + + removal-password: + required: [password] + + # ── Network ─────────────────────────────────────────────────────────────── + proxy-http: + required: [proxy] + + dns-proxy: + required: [app-bundle-id] + optional: + extension-bundle-id: { type: string } + config: { type: object } + + domains: + optional: + email-domains: { type: array } + web-domains: { type: array } + tracking-relaxed-domains: { type: array } + + network-usage-rules: + required: [rules] + + cellular: + optional: + attach-apn: { type: object } + apns: { type: array } + + # ── Content filtering ───────────────────────────────────────────────────── + web-filter: + required: [mode] + optional: + built-in: { type: object } + plugin: { type: object } + + # ── UI shortcuts ────────────────────────────────────────────────────────── + web-clip: + required: [label, url] + optional: + removable: { type: boolean, default: true } + full-screen: { type: boolean, default: false } + icon: { type: string, encoding: base64 } + target-app: { type: string } + + font: + required: [font-name, data] + + # ── Device experience ───────────────────────────────────────────────────── + notifications: + required: [apps] + + sso: + optional: + display-name: { type: string } + kerberos: { type: object } + + identification: + optional: + full-name: { type: string } + email: { type: string } + username: { type: string } + password: { type: string } + prompt: { type: string } + + google-account: + required: [address] + optional: + description: { type: string } + display-name: { type: string } + services: { type: object } + + home-screen: + optional: + dock: { type: array } + pages: { type: array } + + desktop: + optional: + wallpaper: { type: object } + + screensaver: + optional: + module: { type: string } + idle-seconds: { type: integer, default: 300 } + locked: { type: boolean, default: false } + + # ── Enterprise / desktop ────────────────────────────────────────────────── + active-directory: + required: [server] + optional: + admin-username: { type: string } + admin-password: { type: string } + computer-name: { type: string } + organizational-unit: { type: string } + user-experience: { type: object } + password-policy: { type: object } + mobile-accounts: { type: object } + local-admin-groups: { type: array } + uid-mapping: { type: string } + gid-mapping: { type: string } + trust-change-interval-days: { type: integer } + restrict-ddns-interfaces: { type: array } + allow-multi-domain-auth: { type: boolean } + + ad-certificate: + required: [server, template, authority] + optional: + acquisition: { type: enum, values: [rpc, http], default: rpc } + description: { type: string } + key: { type: object } + renewal: { type: object } + prompt-for-credentials: { type: boolean, default: false } + + cert-transparency: + optional: + disabled: { type: object } + required: { type: object } + + time-server: + required: [server] + + software-update: + optional: + catalog-url: { type: string } + automatic: { type: object } + deferral: { type: object } + allow-pre-release: { type: boolean, default: false } + require-admin-to-install: { type: boolean, default: false } + + firewall: + optional: + enabled: { type: boolean, default: false } + block-all-incoming: { type: boolean, default: false } + stealth-mode: { type: boolean, default: false } + apps: { type: array } + + privacy: + required: [services] + + parental-controls: + optional: + apps: { type: object } + web: { type: object } + time-limits: { type: object } + content: { type: object } + + global-preferences: + optional: + multi-session-enabled: { type: boolean, default: false } + + shared-device: + optional: + enabled: { type: boolean, default: true } + temporary-session: { type: object } + user-session: { type: object } + quota-mb: { type: integer } + + education: + required: [organization] + optional: + resource-cert-uuid: { type: string } + device-groups: { type: array } + users: { type: array } + departments: { type: array } + + # ── AirPlay / AirPrint ──────────────────────────────────────────────────── + airprint: + required: [printers] + + airplay: + optional: + allowlist: { type: array } + passwords: { type: array } + + airplay-security: + required: [security, access] + optional: + password: { type: string } + + # ── macOS / desktop system policy ───────────────────────────────────────── + system-policy: + optional: + gatekeeper-enabled: { type: boolean, default: true } + allow-identified-developers: { type: boolean, default: true } + + system-policy-rule: + required: [rules] + + smartcard: + optional: + on-token-removal: { type: enum, values: [none, lock, logout], default: none } + cert-trust: { type: enum, values: [off, basic, ocsp, hard], default: off } + enabled: { type: boolean, default: true } + enforce: { type: boolean, default: false } + user-pairing: { type: boolean, default: true } + one-card-per-user: { type: boolean, default: false } + allow-unmapped-users: { type: boolean, default: true } + + kernel-extension-policy: + optional: + allow-user-approvals: { type: boolean, default: false } + allowed-extensions: { type: array } + + media-management: + required: [media] + + full-disk-encryption: + optional: + state: { type: enum, values: [on, off], default: off } + defer: { type: object } + recovery-key:{ type: object } + escrow-cert: { type: string, encoding: base64 } + cert-uuid: { type: string } + + fde-escrow: + required: [location, encrypt-cert-uuid] + optional: + device-key: { type: string, default: serial-number } + + # ── First boot ──────────────────────────────────────────────────────────── + first-boot: + optional: + skip: { type: array, description: "Pane names to skip on first boot" } + + setup-assistant: + optional: + skip: { type: array, description: "Alias for first-boot — same fields" } diff --git a/schema/profile.schema.yml b/schema/profile.schema.yml new file mode 100644 index 0000000..aaf6976 --- /dev/null +++ b/schema/profile.schema.yml @@ -0,0 +1,535 @@ +# ============================================================================= +# VesperOS Configuration Profile Schema +# Package : vesperprofiled-config-schema +# Version : 1.0.0 +# Installed at: /usr/share/vesperprofiled/schema/profile.schema.yml +# +# vesperprofiled reads this file at startup to determine which payload +# types and fields are valid for this installation. OEMs may ship a +# trimmed version of this schema to restrict which payloads their build +# supports — only payload types listed here will be accepted. +# +# Schema versioning: +# schema-version — incremented when fields are added or removed. +# vesperprofiled checks that its own compiled-in schema-version matches +# or is compatible with the installed schema package version. +# Compatibility rule: daemon >= schema version (newer daemon, older schema ok). +# +# OEM customisation: +# To restrict available payload types, create a trimmed copy of this file +# and ship it as your own vesperprofiled-config-schema package with a +# custom Provides: field. Remove entire payload blocks for unsupported types. +# The daemon will reject any profile containing an unlisted payload type. +# ============================================================================= + +schema-version: "1.0.0" + +# --------------------------------------------------------------------------- +# Allowed payload types for this schema version. +# Remove entries to restrict what profiles may contain on this platform. +# --------------------------------------------------------------------------- +allowed-payload-types: + - mdm + - scep + - pkcs12 + - cert + - cert-preference + - cert-transparency + - wifi + - ethernet + - vpn + - vpn-per-app + - email + - exchange + - caldav + - calendar-subscription + - carddav + - ldap + - passcode + - restrictions + - kiosk + - asam + - proxy-http + - dns-proxy + - domains + - network-usage-rules + - cellular + - web-filter + - web-clip + - font + - notifications + - sso + - active-directory + - ad-certificate + - time-server + - software-update + - firewall + - privacy + - parental-controls + - removal-password + - identification + - google-account + - home-screen + - desktop + - screensaver + - global-preferences + - shared-device + - education + - airprint + - airplay + - airplay-security + - system-policy + - system-policy-rule + - smartcard + - kernel-extension-policy + - media-management + - full-disk-encryption + - fde-escrow + - first-boot + - setup-assistant # alias for first-boot; always include alongside first-boot + +# --------------------------------------------------------------------------- +# Signing requirements by payload type. +# Payloads listed here REQUIRE a signed (CMS/PKCS#7) profile envelope. +# Unsigned profiles containing any of these types will be rejected. +# --------------------------------------------------------------------------- +signing-required: + - mdm + - removal-password + - kiosk + - asam + +# --------------------------------------------------------------------------- +# Singleton payload types. +# Only one instance of each of these is permitted per profile. +# --------------------------------------------------------------------------- +singletons: + - mdm + - passcode + - restrictions + - kiosk + - asam + - proxy-http + - web-filter + - global-preferences + - shared-device + - parental-controls + - removal-password + - identification + - home-screen + - airplay-security + - system-policy + - first-boot + - setup-assistant + +# --------------------------------------------------------------------------- +# Payload field definitions. +# Each entry documents the fields for one payload type. +# The daemon uses this for validation — unknown fields in a profile +# are logged as warnings but do not block installation. +# Required fields that are missing will block installation. +# --------------------------------------------------------------------------- +payloads: + + # ── Top-level profile fields ───────────────────────────────────────────── + profile: + required: [id, uuid, version] + optional: + version: { type: integer, value: 1 } + id: { type: string, pattern: "reverse-dns" } + uuid: { type: string, pattern: "uuid-v4" } + scope: { type: enum, values: [system, user], default: user } + meta: { type: object } + lifecycle: { type: object } + consent: { type: object } + + lifecycle: + optional: + removal: { type: enum, values: [free, locked, password], default: free } + expires-at: { type: string, pattern: "iso8601" } + expires-after: { type: integer, description: "Seconds from install" } + ota-refresh-after: { type: string, pattern: "iso8601" } + + # ── MDM ────────────────────────────────────────────────────────────────── + mdm: + required: [server-url, identity-cert-uuid, access-rights, push-topic] + optional: + checkin-url: { type: string } + sign-messages: { type: boolean, default: false } + checkout-on-removal: { type: boolean, default: false } + use-development-push: { type: boolean, default: false } + capabilities: { type: array } + + # ── SCEP ───────────────────────────────────────────────────────────────── + scep: + required: [url, challenge] + optional: + instance-name: { type: string } + subject: { type: array } + key: { type: object } + san: { type: object } + ca-fingerprint: { type: string, encoding: base64 } + retries: { type: integer, default: 3 } + retry-delay-seconds: { type: integer, default: 10 } + + # ── Certificates ───────────────────────────────────────────────────────── + pkcs12: + required: [data] + optional: + password: { type: string } + all-apps-access: { type: boolean, default: false } + + cert: + required: [data] + + cert-preference: + required: [name, cert-uuid] + + # ── Wi-Fi ──────────────────────────────────────────────────────────────── + wifi: + required: [ssid] + optional: + hidden: { type: boolean, default: false } + auto-join: { type: boolean, default: true } + security: { type: object } + mac-address-mode: { type: enum, values: [hardware, random], default: hardware } + hotspot: { type: object } + proxy: { type: object } + eap: { type: object } + qos-marking: { type: object } + + # ── Ethernet ───────────────────────────────────────────────────────────── + ethernet: + optional: + interface: { type: string, default: first-active } + eap: { type: object } + + # ── VPN ────────────────────────────────────────────────────────────────── + vpn: + optional: + display-name: { type: string } + full-tunnel: { type: boolean, default: false } + on-demand: { type: object } + ikev2: { type: object } + l2tp: { type: object } + custom: { type: object } + + vpn-per-app: + required: [vpn-uuid] + optional: + app-mappings: { type: array } + browser-domains: { type: array } + + # ── Mail accounts ───────────────────────────────────────────────────────── + email: + required: [account, incoming, outgoing] + optional: + smime: { type: object } + restrictions: { type: object } + + exchange: + required: [server, account] + optional: + sync: { type: object } + smime: { type: object } + restrictions: { type: object } + + caldav: + required: [host, username] + optional: + description: { type: string } + port: { type: integer } + ssl: { type: boolean, default: true } + principal-url: { type: string } + password: { type: string } + use-oauth: { type: boolean, default: false } + + calendar-subscription: + required: [url] + optional: + description: { type: string } + username: { type: string } + password: { type: string } + ssl: { type: boolean, default: true } + + carddav: + required: [host, username] + optional: + description: { type: string } + port: { type: integer } + ssl: { type: boolean, default: true } + principal-url: { type: string } + password: { type: string } + use-oauth: { type: boolean, default: false } + + # ── Directory ───────────────────────────────────────────────────────────── + ldap: + required: [host] + optional: + description: { type: string } + ssl: { type: boolean, default: true } + username: { type: string } + password: { type: string } + search-settings: { type: array } + + # ── Security policies ───────────────────────────────────────────────────── + passcode: + optional: + require: { type: boolean, default: true } + allow-simple: { type: boolean, default: true } + require-alphanumeric: { type: boolean, default: false } + min-length: { type: integer, default: 6 } + min-complex-chars: { type: integer, default: 0 } + expiry: { type: object } + lockout: { type: object } + force-change-at-next-login: { type: boolean, default: false } + custom-regex: { type: object } + + restrictions: + optional: + apps: { type: object } + hardware: { type: object } + network: { type: object } + cloud: { type: object } + browser: { type: object } + content-ratings: { type: object } + sharing: { type: object } + open-in: { type: object } + user: { type: object } + input: { type: object } + + kiosk: + required: [app] + optional: + hardware: { type: object } + accessibility:{ type: object } + + asam: + required: [allowed-apps] + + removal-password: + required: [password] + + # ── Network ─────────────────────────────────────────────────────────────── + proxy-http: + required: [proxy] + + dns-proxy: + required: [app-bundle-id] + optional: + extension-bundle-id: { type: string } + config: { type: object } + + domains: + optional: + email-domains: { type: array } + web-domains: { type: array } + tracking-relaxed-domains: { type: array } + + network-usage-rules: + required: [rules] + + cellular: + optional: + attach-apn: { type: object } + apns: { type: array } + + # ── Content filtering ───────────────────────────────────────────────────── + web-filter: + required: [mode] + optional: + built-in: { type: object } + plugin: { type: object } + + # ── UI shortcuts ────────────────────────────────────────────────────────── + web-clip: + required: [label, url] + optional: + removable: { type: boolean, default: true } + full-screen: { type: boolean, default: false } + icon: { type: string, encoding: base64 } + target-app: { type: string } + + font: + required: [font-name, data] + + # ── Device experience ───────────────────────────────────────────────────── + notifications: + required: [apps] + + sso: + optional: + display-name: { type: string } + kerberos: { type: object } + + identification: + optional: + full-name: { type: string } + email: { type: string } + username: { type: string } + password: { type: string } + prompt: { type: string } + + google-account: + required: [address] + optional: + description: { type: string } + display-name: { type: string } + services: { type: object } + + home-screen: + optional: + dock: { type: array } + pages: { type: array } + + desktop: + optional: + wallpaper: { type: object } + + screensaver: + optional: + module: { type: string } + idle-seconds: { type: integer, default: 300 } + locked: { type: boolean, default: false } + + # ── Enterprise / desktop ────────────────────────────────────────────────── + active-directory: + required: [server] + optional: + admin-username: { type: string } + admin-password: { type: string } + computer-name: { type: string } + organizational-unit: { type: string } + user-experience: { type: object } + password-policy: { type: object } + mobile-accounts: { type: object } + local-admin-groups: { type: array } + uid-mapping: { type: string } + gid-mapping: { type: string } + trust-change-interval-days: { type: integer } + restrict-ddns-interfaces: { type: array } + allow-multi-domain-auth: { type: boolean } + + ad-certificate: + required: [server, template, authority] + optional: + acquisition: { type: enum, values: [rpc, http], default: rpc } + description: { type: string } + key: { type: object } + renewal: { type: object } + prompt-for-credentials: { type: boolean, default: false } + + cert-transparency: + optional: + disabled: { type: object } + required: { type: object } + + time-server: + required: [server] + + software-update: + optional: + catalog-url: { type: string } + automatic: { type: object } + deferral: { type: object } + allow-pre-release: { type: boolean, default: false } + require-admin-to-install: { type: boolean, default: false } + + firewall: + optional: + enabled: { type: boolean, default: false } + block-all-incoming: { type: boolean, default: false } + stealth-mode: { type: boolean, default: false } + apps: { type: array } + + privacy: + required: [services] + + parental-controls: + optional: + apps: { type: object } + web: { type: object } + time-limits: { type: object } + content: { type: object } + + global-preferences: + optional: + multi-session-enabled: { type: boolean, default: false } + + shared-device: + optional: + enabled: { type: boolean, default: true } + temporary-session: { type: object } + user-session: { type: object } + quota-mb: { type: integer } + + education: + required: [organization] + optional: + resource-cert-uuid: { type: string } + device-groups: { type: array } + users: { type: array } + departments: { type: array } + + # ── AirPlay / AirPrint ──────────────────────────────────────────────────── + airprint: + required: [printers] + + airplay: + optional: + allowlist: { type: array } + passwords: { type: array } + + airplay-security: + required: [security, access] + optional: + password: { type: string } + + # ── macOS / desktop system policy ───────────────────────────────────────── + system-policy: + optional: + gatekeeper-enabled: { type: boolean, default: true } + allow-identified-developers: { type: boolean, default: true } + + system-policy-rule: + required: [rules] + + smartcard: + optional: + on-token-removal: { type: enum, values: [none, lock, logout], default: none } + cert-trust: { type: enum, values: [off, basic, ocsp, hard], default: off } + enabled: { type: boolean, default: true } + enforce: { type: boolean, default: false } + user-pairing: { type: boolean, default: true } + one-card-per-user: { type: boolean, default: false } + allow-unmapped-users: { type: boolean, default: true } + + kernel-extension-policy: + optional: + allow-user-approvals: { type: boolean, default: false } + allowed-extensions: { type: array } + + media-management: + required: [media] + + full-disk-encryption: + optional: + state: { type: enum, values: [on, off], default: off } + defer: { type: object } + recovery-key:{ type: object } + escrow-cert: { type: string, encoding: base64 } + cert-uuid: { type: string } + + fde-escrow: + required: [location, encrypt-cert-uuid] + optional: + device-key: { type: string, default: serial-number } + + # ── First boot ──────────────────────────────────────────────────────────── + first-boot: + optional: + skip: { type: array, description: "Pane names to skip on first boot" } + + setup-assistant: + optional: + skip: { type: array, description: "Alias for first-boot — same fields" }