# Concepts

Core concepts of the templating-vault system.

## Key Structure

Keys use dots as separators forming a tree: `global.credentials.forgejo_pat`

On disk, each segment becomes a directory. A key with a value has a `value` file.
Optional `meta.yaml` alongside it holds metadata.

```
<data_dir>/
  .store.yaml                  # Store-level defaults
  global/
    credentials/
      forgejo_pat/
        value                  # The raw value text
        meta.yaml              # Per-key metadata
      forgejo_username/
        value
  session/
    max_workers/
      value
```

**Rules:**
- Only keys with `value` files are "set" and appear in listings
- A key can have both a value AND sub-keys (e.g., `foo` has a value, `foo.bar` also has a value)
- Namespace-only directories (no `value` file) are invisible to `list.ts`
- Key names: `[a-zA-Z0-9_-]+` per segment, separated by dots. No leading/trailing/consecutive dots.

## Key Metadata (meta.yaml)

Each key can have a `meta.yaml` file defining its properties:

```yaml
literal: true          # Must use extract.ts, not set.ts (at write access)
readonly: false         # Cannot be modified even with write access
write_once: true        # Can only be set once, then locked forever
owner: "primary"        # Creator identity for access control
type: positive_integer  # Built-in type validator
template: false         # If true, value is a Nunjucks expression evaluated on read
on_absent: "error"      # For template deps: default value if dependency missing, or "error"
description: "..."      # Human-readable description
validate:               # Custom regex validation
  regex: "^[0-9a-f]{40}$"
  message: "Must be 40-char hex"
```

Properties not specified in `meta.yaml` inherit from the store's `.store.yaml` defaults,
then from built-in defaults (`literal: false`, `type: string`, `write_once: false`, etc.).

## Store Defaults (.store.yaml)

Each data directory can have a `.store.yaml` at its root:

```yaml
defaults:
  literal: false
  readonly: false
  write_once: false
  type: string
  template: false
  on_absent: "error"
```

## Built-in Type Validators

| Type | Rule |
|------|------|
| `string` | Any text (default) |
| `nonempty` | Non-empty string |
| `number` | Valid float |
| `integer` | Valid integer |
| `positive_integer` | Integer > 0 |
| `boolean` | `"true"` or `"false"` |
| `url` | Starts with `http://` or `https://` |
| `hex` | Matches `/^[0-9a-fA-F]+$/` |

Custom validation via `validate.regex` in `meta.yaml`. Value must match the pattern.

## Access Levels

Each store mapping has an access level:

| Level | Read | Set non-literal | Extract literal | Modify metadata |
|-------|------|-----------------|-----------------|-----------------|
| `readonly` | yes | no | no | no |
| `write` | yes | yes | yes | no |
| `admin` | yes | yes (including literals) | yes | yes |

Access is set per-store in the config.yaml or defaults to `write` for CLI `--store-dir`.

## Literal vs Non-Literal

**Literal** variables contain values that must be preserved character-for-character
(credentials, tokens, URLs). They can only be stored via:
- `extract.ts` with a regex (the script extracts from source text, LLM provides only the regex)
- `set.ts` with `admin` access (for bootstrap from env vars via shell expansion)

**Non-literal** variables contain inferred/computed values. The LLM can set them
directly via `set.ts`.

The literal/non-literal classification is defined in:
- Per-key `meta.yaml` files (the `literal:` field)
- Template `schema.yaml` files (for prompt templates)
- Store `.store.yaml` defaults

## Computed Values (Templates)

A key with `template: true` in its metadata holds a Nunjucks expression instead of
a raw value. When read via `get.ts`, the expression is evaluated lazily using all
non-template values in the configured stores as variables.

```
# Stored as value file content:
{{ (max_workers | default(4) / 8) | round(0, "ceil") | int }}

# When max_workers = 16, get.ts returns: "2"
```

Nunjucks filters available: `default`, `round`, `int`, `ceil`, `floor`, `abs`, `max`, `min`,
`upper`, `lower`, `trim`, `length`, plus all standard Nunjucks built-ins.

## Template Schema (schema.yaml)

Template keys can have a `schema.yaml` in their directory defining each variable:

```yaml
variables:
  forgejo_pat:
    literal: true
    type: hex
    description: "Forgejo PAT"
  max_workers:
    literal: false
    type: positive_integer
```

This schema is copied into prepared prompts (via `render.ts --prepare`) and returned
by `retrieve.ts`, so the child agent knows which variables need regex extraction vs
direct setting.
