# Advanced

---

# Private hives and layers

_Peios / Using Peios / Advanced_

> Private hives and layers give one caller its own view of the registry — the building block for sandboxing, with authorisation deferred to KACS.

Everything in the core topic describes one shared registry that every process sees the same way (subject to access control). **Private hives** and **private layers** relax that: they let a particular caller see a registry that differs from everyone else's — the building block for sandboxing and container-style isolation.

This is an advanced feature, and a partly forward-looking one. The registry defines how a private hive or layer participates in [resolution](/peios/using-peios/registry-layers/layers.md); but *who* is allowed to see one is decided by a thread's credentials, and that credential model is part of KACS and not yet fully specified. Treat this page as the shape of the feature, not a how-to.

## Private hives

A **private hive** is a hive that is visible only to threads whose credentials carry a matching scope — an opaque identity that marks "you are allowed to see this hive". To everyone else it does not exist.

The powerful case is **shadowing**. A private hive can take the same name as a global one — `Machine\`, say — and for a thread that carries the scope, the private hive is what `Machine\` resolves to, not the global one. A sandboxed process can therefore be given an entirely separate `Machine\` while every other process continues to see the real one, with no change to the paths anyone uses. That is complete registry isolation without a parallel namespace: same paths, different contents, decided by who is asking.

## Private layers

A **private layer** is a [layer](/peios/using-peios/registry-layers/layers.md) that is globally disabled — invisible in normal resolution — but attached to a specific thread's credentials. For that thread, and only that thread, the layer is treated as active and competes in the per-value contest at its precedence exactly like any other layer. Everyone else resolves as if it were not there.

This is the lighter-weight tool, for when you want a different *value* here and there rather than a whole separate hive:

- **Per-session overrides** — run one application with experimental settings without disturbing other sessions.
- **Testing** — inject configuration for one process without writing it into the shared registry.
- **Sandboxing** — give a confined process a slightly different view without standing up a private hive.

Private layers are **per thread, not per process**: because the attachment rides on a thread's credentials, different threads in the same process can carry different private layers (for instance, a service thread acting on behalf of a particular client). The number a thread can carry is bounded.

## Authorisation lives in KACS

The registry defines only the *resolution* behaviour — private hives are checked ahead of global ones, and a thread's private layers fold into its contests. The decision about whether a thread may join a scope or attach a layer belongs to KACS's credential model. One constraint is already clear and worth stating: attaching a layer that sits *above* others in precedence must be privileged, or an unprivileged process could attach an existing high-precedence policy layer to itself and gain a window onto configuration it should not see or influence. The isolation is only as strong as the rule that decides who may carry a scope or a private layer.

## Where to go next

For the resolution model these build on — precedence, recency, and the per-value contest — read [Layers](/peios/using-peios/registry-layers/layers.md).

For where private hives are routed and served, read [LCS and sources](/peios/using-peios/registry-administration/lcs-and-sources.md).

---

# Transactions

_Peios / Using Peios / Advanced_

> A transaction groups several registry writes into one all-or-nothing commit — how a role installs without ever being half-applied.

Most registry writes stand alone. But sometimes a set of changes only makes sense *together* — a role's keys and values are one coherent configuration, and a half-written version would be worse than none at all. A **transaction** makes several writes atomic: all of them commit, or none do. This is a developer-facing feature — you reach for it when *writing* to the registry, not when operating a running system — which is why it sits among the advanced topics.

## Transactions, in one sentence

**A transaction groups many registry writes into one all-or-nothing commit, so other readers only ever see the complete change, never a partial one.**

## All or nothing

Inside a transaction you perform a series of writes and then commit. At commit, they all take effect together. If you abort instead — or the process dies, or the transaction sits open too long and times out — none of them take effect. There is no partial application.

External readers see only committed state. Until you commit, your in-progress writes are invisible to everyone else; the instant you commit, the whole set appears at once. A service reading configuration never catches a transaction halfway. Within your own transaction you *do* see your own pending writes, so you can write a value and read it back before committing.

## The canonical use: installing a role

This is why [role installation](/peios/using-peios/registry-layers/what-layers-are-for.md) is clean. A role's entire configuration — its keys, its values, its layer — is written inside one transaction and committed as a unit. The role is never observed half-installed: either the whole role is there or none of it is. (Removing a role is the *other* mechanism — deleting its layer — covered with [layers](/peios/using-peios/registry-layers/what-layers-are-for.md).)

Any consistent multi-key update wants the same treatment: change several related settings as one atomic step, rather than letting readers see an inconsistent in-between.

## Limits worth knowing

- **One store at a time.** A transaction is scoped to a single hive's store; it cannot span hives backed by different [sources](/peios/using-peios/registry-administration/lcs-and-sources.md). Atomicity across separate stores is not offered.
- **No nesting.** Transactions are flat — there are no sub-transactions or savepoints.
- **Bounded lifetime.** An open transaction holds a write position, so it cannot be left open indefinitely; if it is not committed in time it is aborted automatically. This stops a stalled or abandoned writer from blocking everyone else's writes to that store.
- **Abandonment is safe.** Closing the handle without committing aborts cleanly, and a process dying does the same — there are no orphaned transactions left holding things up.

## Transactions and layers

A transaction provides *atomicity*; it is not a [layer](/peios/using-peios/registry-layers/layers.md) and it does not change which write wins. The two compose: a role install uses a transaction to apply its writes atomically *and* a layer to make them removable later. Keep them distinct — atomicity is "all together", layering is "which one wins, and how to revert".

Transactions are not conflict-detected at the value level. If two committed transactions wrote the same value, both succeed, and the usual rule settles it: the more recent write wins, exactly as in [layer resolution](/peios/using-peios/registry-layers/layers.md). A transaction guarantees its *own* writes land together; it does not lock anyone else out of the values it touched. (For the case where you must not clobber a concurrent change, a conditional write lets a single write proceed only if the value has not changed since you read it.)

## Where to go next

For how a role uses a transaction and a layer together, read [What layers are for](/peios/using-peios/registry-layers/what-layers-are-for.md).

For the recency rule that settles competing writes, read [Layers](/peios/using-peios/registry-layers/layers.md).

---

# Registry links

_Peios / Using Peios / Advanced_

> A key can be a symbolic link to another key — the one place the registry interprets a value — with layered targets and privileged creation.

A registry key can be a **symbolic link** to another key. Open a link key by its path and the registry follows it through to the target, handing you a handle on the target key. Links let one part of the namespace point at another, the way a filesystem symlink does.

Links are an advanced feature with a small, sharp set of rules, and they are the **one exception** to a property the rest of the topic relies on.

## A link is a flag plus a target value

Two pieces make a link, and both are needed:

- The key is **marked** as a link when it is created. This is a fixed property of the key.
- The key's **default value**, of type `REG_LINK`, holds the **target path** — an absolute registry path the link points at.

When path resolution reaches a link key, the registry reads that target and continues resolving from there; the handle you get back refers to the target, not the link.

## The one place the registry reads a value

[Keys, values, and types](/peios/using-peios/registry-concepts/keys-values-and-types.md) made a point of it: the registry stores a value's type and bytes but never interprets them. `REG_LINK` is the single exception. It is the one type the registry acts on itself — following it during path resolution — rather than handing it back untouched. Everything else remains opaque; links are the lone case where the store cares what a value *says*.

## Managing the link itself

Normally you want to follow a link. To operate on the link key *itself* — to change where it points or delete it — you open it with a flag that says "open the link, do not follow it". Without that flag every open lands on the target, which would make the link impossible to manage.

## Creating a link is privileged

Because a link silently redirects whoever opens it, creating one is restricted. It requires the `KEY_CREATE_LINK` right on the parent **and** a privileged caller (the system-trust privilege, or Administrator membership). A link is a small piece of trusted plumbing, not something an ordinary process gets to introduce into a path other callers will traverse.

There is one safety rule worth knowing: a link target is followed **literally**, and the `CurrentUser\` convenience alias is *not* expanded inside it. This stops a link from redirecting a privileged service that resolves `CurrentUser\` into the service's *own* user hive — a classic confused-deputy trap. Link targets route by their literal hive name. Resolution is also bounded by a hop limit, so a cycle of links fails rather than looping forever.

## Layers can redirect a link

The target is an ordinary [layered](/peios/using-peios/registry-layers/layers.md) value — the link key's default value — so it plays by the same rules as any other value. A higher-precedence or more-recent layer can write a *different* `REG_LINK` target and redirect the link; remove that layer and the original target resurfaces, by the usual automatic revert. And if a layer writes a default value that is *not* a `REG_LINK` onto a key that is still flagged as a link, resolution through it fails until the offending layer is removed or overridden. The link's *identity* is fixed at creation; its *target* is just configuration, and configuration is layered.

## Where to go next

For the opaque-value rule this is the exception to, read [Keys, values, and types](/peios/using-peios/registry-concepts/keys-values-and-types.md).

For how a layer can redirect or break a link, read [Layers](/peios/using-peios/registry-layers/layers.md).
