# Propsec
Schema enforcement for Obsidian properties.
Define schemas based on templates or invariants in your vault, add custom reusable types, and more.
# Usage
First, define a schema:
Once saved, violating notes such as this one...
...will be caught by the validation:
## Why
Obsidian properties are freeform. Over time, things can break: you change the structure, use an old field, etc. This plugin validates notes against schemas you define. Your notes are untouched, but your vault's consistency becomes easier to manage.
## Setup
1. Open plugin settings
2. Create a schema: click **+ Add Schema**
3. Set a query to target notes
4. Add fields: name, type, required/optional
5. Violations appear in the status bar/sidebar
## Schema definition
The query field allows schema matching based on file paths and/or tags:
| Query | Matches |
|-------|---------|
| `Journal` | Notes directly in Journal folder |
| `Journal/*` | Notes in Journal and all subfolders |
| `#book` | Notes with #book tag |
| `Projects/* or #active` | Notes matching either condition |
You can also narrow which notes a schema applies to with properties:
- `File name matches`: Filter by file name (regex)
- `Modified after` / `Modified before`: Filter by modification date
- `Created after` / `Created before`: Filter by creation date
- `Has property` / `Missing property`: Filter by property existence
- `Property conditions`: Filter by property values (property-operator-value list)
## Field types
### Primitives
`string`, `number`, `boolean`, `date`, `array`, `object`, `null`, `unknown`
### Custom types
Define reusable types in settings. A custom type is a named group of fields. Use them when multiple schemas share the same structure or you need nested validation.
### Union types
Add multiple field entries with the same name but different types. For example, two entries for `status` with types `string` and `null` creates `string | null`.
## Field flags
Fields can be flagged to be **required** (key is required) xor **warn** (soft requirement). There is also a **unique** constraint that prevents duplicate values on that field.
Finally, there are **cross-field constraints** (compare this field's value to another field) and **conditional validation** (only validate this field when another field matches a condition).
## Constraints
Each field type supports optional constraints:
| Type | Constraints |
|------|-------------|
| string | `pattern` (regex), `minLength`, `maxLength` |
| number | `min`, `max` |
| array | `minItems`, `maxItems`, `contains` (required values) |
| date | `min`, `max` |
## Installation
Copy to `.obsidian/plugins/` or install via BRAT.