Documentation
¶
Overview ¶
Package trust holds the rules about folders the user vouches for.
Everything here is a pure function of a path, the home directory, and the config-tree guard: no live site, no session manager, no app mutex, and nothing that reads the declared list. That is deliberate. These rules are what stands between a page and a durable write grant over a tree, so they should be readable and testable without standing up an HTTP server, a port, and a temp home first.
The declared list itself stays in package main, next to the sites it anchors: adding and removing a folder has to move listeners and registrations, so it is app work, not policy.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IdentityOK ¶
IdentityOK reports whether the directory at path is still provably the one that was declared. An empty pin (a platform without fingerprints) leaves the path as the entry's whole identity.
Types ¶
type Policy ¶
type Policy struct {
Home string
// Guard reports whether dir touches HTML Clay's own config tree, in either
// direction. The app owns it because only the app knows where that tree is.
Guard func(dir string) bool
}
Policy answers "may this folder be trusted, and on whose say-so".
func (Policy) Canonical ¶
Canonical resolves and validates a folder the user asked to trust, returning the canonical path to store. The folder must resolve, sit strictly inside home (so home itself is refused), carry no hidden component, and not be HTML Clay's own config/versions tree. Storing the same canonical form the session manager keys its roots on is what keeps live-revoke able to find the root later.
func (Policy) IsPersonal ¶
IsPersonal reports whether dir is exactly one of the personal folders. The tray picker uses it to warn before trusting one; unlike the two rules above it refuses nothing, because a deliberate act with a folder picker may choose anything Canonical accepts.
func (Policy) RefuseOwnFolder ¶
RefuseOwnFolder reports whether dir is a personal folder, or an ancestor that would swallow one.
This is the rule for the route where the folder is pinned to a file the user acted on: it is always the requesting file's own directory, so a page cannot inflate it. That makes the looser test correct here, and the stricter one wrong: ~/Documents/GitHub/myproject must stay trustable by a file inside it. A folder INSIDE a personal folder is therefore allowed, which is the whole difference from RefuseSteered.
Comparison is by identity (os.SameFile) as well as case-folded path, so a casing alias or a symlinked variant of a personal folder cannot slip through as a different spelling.
func (Policy) RefuseSteered ¶
RefuseSteered reports whether dir is a personal folder, sits inside one, or is an ancestor that would swallow one.
This is the rule for the route where the PAGE steers which folder is named. The read prompt offers to trust the common ancestor of the requesting file and the asset it asked for, and a page picks its own assets: two requests under different subfolders make their common ancestor the whole of Documents. One click would then durably trust everything the user owns.
Note what that means in practice, because it is broader than it first reads and the honest case does pay for it: ANYTHING under a personal folder is refused on this route, so someone whose projects live in ~/Documents or ~/Desktop never sees this button. The other two doors are still open to them, the banner on a file they opened (RefuseOwnFolder, which allows exactly that case) and the tray picker, which consults none of this because choosing a folder from a picker is already a deliberate act.
dir arrives already symlink-resolved, so each name is compared in both its lexical and its resolved form. A Downloads or Documents folder that is itself a symlink, pointing at an external drive or a synced folder, is an ordinary setup, and it would otherwise reach here under its target's name and sail past a purely lexical match. Folders the user has renamed outright are still not recognized.