# 5.3.5 Private Layers

_Peios / Advanced Peios / PKM / LCS / Layers_

> A disabled layer attached to a thread's credentials — how it resolves, how it is attached, and the privilege that is deliberately not checked.

A private layer is a **disabled** layer attached to a thread's
credentials. It is invisible during ordinary resolution and treated as
enabled when resolving on behalf of a thread whose token names it.

That covers three things a shared registry otherwise cannot do: giving
one session experimental settings without affecting others; injecting
test configuration without touching the shared tree; and giving a
container a different view of the registry without a separate hive.

## 5.3.5.1 Resolution

A private layer participates in normal precedence ordering. A disabled
layer with precedence 5 attached to a thread resolves at precedence 5,
competing with everything else at that level. It is not an overlay on
top; it is a layer that only that thread can see.

The activity test is exactly: a layer is active for a thread if it is
globally enabled, or its name appears in that thread's private layer
set. Name matching uses Unicode Simple Case Folding, like every other
layer name comparison.

## 5.3.5.2 Attachment

Private layer names reach a thread through the KACS token's LCS
credential extension — the same versioned block that carries scope
GUIDs for private hives (§5.2.2). LCS reads the credentials from the
effective token on each operation and passes them into resolution.

Private layers are therefore **per-thread, not per-process**: threads
in one process can hold different private layer sets through different
impersonation tokens.

## 5.3.5.3 Two things about the caps

`MaxPrivateLayersPerToken`, default 16, is described as a limit on
attachment. It is not enforced there. KACS applies its own hard cap of
256 names when it parses the token specification, and the configurable
LCS limit is applied later, when LCS acquires a thread's private
credentials for an operation.

The consequence is that a token carrying seventeen private layers is
accepted by KACS and then fails every LCS operation, rather than being
refused when it was built. Reading LCS's configured limits from KACS
would invert the dependency between the two, so the cap stays where it
can be read.

The failure is `E2BIG`. It was `EACCES`, which read as an access-control
denial and sent anyone debugging it towards descriptors and privileges
rather than towards a count that was fixed when the token was assembled,
possibly in another process. `MaxScopeGUIDsPerToken` shares the check
and the errno. A missing token is still `EACCES`, because that one is an
access decision.

KACS also deduplicates private layer names using ASCII case-insensitive
comparison, where LCS matches them with Unicode Simple Case Folding.
Two names that LCS would treat as one layer can both sit on a token.

## 5.3.5.4 The privilege that is not checked

Attaching a private layer whose precedence is above 0 ought to require
`SeTcbPrivilege` — otherwise an unprivileged process can attach an
existing high-precedence disabled layer to its own credentials and see,
and potentially influence, Group Policy-tier configuration.

**That check does not exist.** KACS never consults the LCS layer table
when parsing the credential extension, and there is no precedence
lookup and no privilege test anywhere on the attachment path. What does
gate attachment is `SeCreateTokenPrivilege`, because private layer
names can only enter a token when the token is created — the same
blanket gate that governs scope GUIDs.
