Add fs-home: the machine's home directory, grant-checked
A client that wants to expand "~" must not hardcode a host convention. The home that matters is the BROWSED machine's, which for a remote node (Familiar) is not the machine doing the typing — so it has to come from the capability surface like every other fact about that filesystem.
Grant-checked as a READ OF the home directory, deliberately: a principal scoped to /srv has no business learning where the owner's home is, and anything it would do with the answer (list it, read from it) is denied anyway. Under the in-process desktop posture (grant-allow-all) it is simply always allowed.
Raises when HOME is unset (a bare service environment); callers should read that as "no home to expand", not as fatal.
Ships in the same 0.1.1 as the canonical read-dir order.
src/sigil/system/fs.sgl | 23 +++++++++++++++++++++++
test/test-system.sgl | 18 ++++++++++++++++++
2 files changed, 41 insertions(+)src/sigil/system/fs.sglmodified
(sigil path) (sigil io) (sigil string) ; string<? / string-downcase (listing order) (sigil process) ; getenv (fs-home) (sigil system grant)) (export fs-home fs-read-dir fs-stat fs-read-file mtime: (stat-mtime st) mode: (stat-mode st))) ;;; The user's home directory, canonicalized. Raises when HOME is ;;; unset (a bare service environment) — callers should treat that as ;;; "no home to expand", not as fatal. ;;; ;;; Grant-checked as a READ OF that directory, deliberately: a ;;; principal scoped to /srv has no business learning where the ;;; owner's home is, and anything it would do with the answer (list ;;; it, read from it) would be denied anyway. Under the in-process ;;; desktop posture (grant-allow-all) this is simply always allowed. ;;; ;;; Exists so a client can expand "~" WITHOUT hardcoding a host ;;; convention: the path belongs to the machine being browsed, which ;;; for a remote node (Familiar) is not the machine typing. (define (fs-home g) (: any? -> string?) (let ((home (getenv "HOME"))) (unless home (error "fs-home: HOME is not set")) (grant-assert! g 'fs-read home) (or (realpath home) home))) ;;; Stat a file or directory. Returns a dict with `name:` `path:` ;;; `type:` `size:` `mtime:` `mode:`, or raises if the path does ;;; not exist.test/test-system.sglmodified
(sigil io) (sigil fs) (sigil path) (sigil process) ; getenv (fs-home tests) (sigil string) (sigil async) (sigil channels) (fs-write-file g path "hi there\n") (assert-equal (fs-read-file g path) "hi there\n")))) (test "fs-home returns the home directory when granted" ;; Exists so a client can expand "~" without hardcoding a host convention — ;; on a remote node the home that matters is the NODE's, not the one typing. (let ((g (make-grants)) (home (getenv "HOME"))) (grant-add! g (string-append "fs:ro:" home)) (assert-equal (fs-home g) (or (realpath home) home)))) (test "fs-home is DENIED to a principal scoped elsewhere" ;; Grant-checked as a read OF home on purpose: a principal scoped to a project ;; directory has no business learning where the owner's home is, and everything ;; it could do with the answer would be denied anyway. (let ((g (make-grants)) (dir (make-temp-directory))) (grant-add! g (string-append "fs:rw:" dir)) (assert-true (guard (e (#t #t)) (fs-home g) #f)))) (test "read-dir returns stat dicts" (let ((g (make-grants)) (dir (make-temp-directory)))