Separate filesystem context from access

This commit is contained in:
2026-10-25 13:09:44 +00:00
parent 0d149e51f0
commit 6158e9db3b
5 changed files with 180 additions and 112 deletions

View File

@@ -1,6 +1,6 @@
# Consolidation Implementation Plan
Status: in progress. Stages 1 through 6 are complete; follow Stage 7 through Stage 20 in order.
Status: in progress. Stages 1 through 7 are complete; follow Stage 8 through Stage 20 in order.
The target executor is a Luna coding agent working through one end-to-end sprint.
## Authority, Baseline, And Execution
@@ -347,7 +347,7 @@ direct tests to construct named requests. A search-source regression was caught
and fixed during verification. The focused engine selection, facade selection,
consumer example tests, and `GOTOOLCHAIN=local GOPROXY=off go test ./...` passed.
## Stage 7 — Separate Resolved Filesystem Facts From Access
## Stage 7 — Separate Resolved Filesystem Facts From Access (Complete)
**Owners:** new engine `filesystem_context.go`, `filesystem.go`,
`filesystem_access.go`.
@@ -374,6 +374,13 @@ consumer example tests, and `GOTOOLCHAIN=local GOPROXY=off go test ./...` passed
**Finish:** common context facts have one private representation while validation
timing and live resource ownership remain explicit.
Progress notes (2026-10-25): added shared host/native filesystem descriptions,
separated directory validation and access creation, and migrated import
acquisition to pass resolved facts alongside its owned access. The prior
derivation adapters remain for the validator and overlay migration. Focused
acquisition tests, `GOTOOLCHAIN=local GOPROXY=off go test ./...`, and
`git diff --check` passed.
## Stage 8 — Carry Context Facts Through Input And Passive Views
**Owners:** engine `load_input.go`, `source_context.go`, `load_request.go`, and

View File

@@ -33,14 +33,6 @@ type importAcquisitionRequest struct {
processing *sourceVersionProcessingResult
}
type resolvedFilesystemContext struct {
native *nativeNamespace
hostToken *namespaceToken
rootPath string
basePath string
mainPath string
}
func acquireInput(request inputAcquisitionRequest, policy acquisitionPolicy, state *acquisitionState, tier *tierAcquisitionState) (assembledInput, []Diagnostic) {
source := request.input.source
destination := request.input.destination

View File

@@ -3,7 +3,6 @@ package engine
import (
"io/fs"
"os"
"path"
"path/filepath"
"strings"
)
@@ -137,32 +136,17 @@ func nativeContext(source Source, context *FilesystemContext) bool {
// nativeFilesystemAccess resolves namespace context without opening caller
// resources. File inputs always derive their base from the selected file.
func nativeFilesystemAccess(source Source, context *FilesystemContext) (*filesystemAccess, string, string, *Diagnostic) {
var namespace *nativeNamespace
rootPath := "."
basePath := "."
mainPath := ""
if source.kind == sourceFilesystem {
namespace = source.namespace
mainPath = source.path
basePath = path.Dir(source.path)
if context != nil && context.Root != "" {
rootPath = context.Root
}
} else if context != nil && context.FS != nil {
namespace = context.FS.namespace
rootPath, basePath = context.Root, context.BaseDir
resolved, diagnostic := resolveNativeFilesystemContext(source, context)
if diagnostic != nil {
return nil, "", "", diagnostic
}
if namespace == nil || nilFilesystem(namespace.filesystem) || !fs.ValidPath(rootPath) || !fs.ValidPath(basePath) {
value := optionDiagnostic(CodeOptionsInvalid, "filesystem context is invalid")
access, err := openResolvedFilesystemAccess(resolved)
if err != nil {
value := globFilesystemDiagnostic(err, "configuration root could not be opened", Location{})
value.Primary = nil
return nil, "", "", &value
}
access := newNativeAccess(namespace.filesystem, rootPath, namespace.token)
access.label = namespace.label
if !access.contains(basePath) || mainPath != "" && !access.contains(mainPath) {
value := importDiagnostic(CodeImportOutsideRoot, "selected source and import base must stay inside the configuration root", nil)
return nil, "", "", &value
}
return access, basePath, mainPath, nil
return access, resolved.basePath, resolved.mainPath, nil
}
func validateNativeDirectories(access *filesystemAccess, basePath, mainPath string) *Diagnostic {
@@ -181,64 +165,14 @@ func validateNativeDirectories(access *filesystemAccess, basePath, mainPath stri
}
func importFilesystem(source Source, context *FilesystemContext, main parsedSource) (rootPath, basePath, mainPath string, diagnostic *Diagnostic) {
if main.source == nil || main.document == nil {
value := importDiagnostic(CodeImportInvalid, "imports require a selected configuration source", nil)
return "", "", "", &value
resolved, diagnostic := resolveHostFilesystemContext(source, context, main, nil)
if diagnostic != nil {
return "", "", "", diagnostic
}
if source.kind == sourceFile {
if context != nil && context.BaseDir != "" {
value := optionDiagnostic(CodeOptionsInvalid, "file sources determine their own import base directory")
return "", "", "", &value
}
canonical, err := canonicalExistingPath(source.path)
if err != nil {
value := importDiagnostic(CodeImportInvalid, "selected source path could not be canonicalized", nil)
return "", "", "", &value
}
mainPath = canonical
basePath = filepath.Dir(canonical)
rootPath = basePath
if context != nil && context.Root != "" {
rootPath, err = canonicalExistingPath(context.Root)
if err != nil {
value := importDiagnostic(CodeImportInvalid, "configuration root could not be canonicalized", nil)
return "", "", "", &value
}
}
} else {
if context == nil || context.BaseDir == "" || context.Root == "" {
value := optionDiagnostic(CodeOptionsInvalid, "byte and reader imports require absolute base and root directories")
return "", "", "", &value
}
if !filepath.IsAbs(context.BaseDir) || !filepath.IsAbs(context.Root) {
value := optionDiagnostic(CodeOptionsInvalid, "byte and reader import base and root directories must be absolute")
return "", "", "", &value
}
var err error
basePath, err = canonicalExistingPath(context.BaseDir)
if err != nil {
value := importDiagnostic(CodeImportInvalid, "import base directory could not be canonicalized", nil)
return "", "", "", &value
}
rootPath, err = canonicalExistingPath(context.Root)
if err != nil {
value := importDiagnostic(CodeImportInvalid, "configuration root could not be canonicalized", nil)
return "", "", "", &value
}
if diagnostic := validateResolvedFilesystemDirectories(resolved); diagnostic != nil {
return "", "", "", diagnostic
}
if !containedPath(rootPath, basePath) || (mainPath != "" && !containedPath(rootPath, mainPath)) {
value := importDiagnostic(CodeImportOutsideRoot, "selected source and import base must stay inside the configuration root", nil)
return "", "", "", &value
}
for _, candidate := range []string{rootPath, basePath} {
info, err := os.Stat(candidate)
if err != nil || !info.IsDir() {
value := importDiagnostic(CodeImportInvalid, "configuration root and import base must be directories", nil)
return "", "", "", &value
}
}
return rootPath, basePath, mainPath, nil
return resolved.rootPath, resolved.basePath, resolved.mainPath, nil
}
func canonicalExistingPath(name string) (string, error) {

View File

@@ -0,0 +1,149 @@
package engine
import (
"io/fs"
"os"
"path"
"path/filepath"
"strings"
)
type resolvedFilesystemContext struct {
native *nativeNamespace
hostToken *namespaceToken
rootPath string
basePath string
mainPath string
}
func resolveFilesystemContext(source Source, context *FilesystemContext, main parsedSource, hostToken *namespaceToken) (resolvedFilesystemContext, *Diagnostic) {
if nativeContext(source, context) {
return resolveNativeFilesystemContext(source, context)
}
return resolveHostFilesystemContext(source, context, main, hostToken)
}
func resolveNativeFilesystemContext(source Source, context *FilesystemContext) (resolvedFilesystemContext, *Diagnostic) {
var namespace *nativeNamespace
resolved := resolvedFilesystemContext{rootPath: ".", basePath: "."}
if source.kind == sourceFilesystem {
namespace = source.namespace
resolved.mainPath = source.path
resolved.basePath = path.Dir(source.path)
if context != nil && context.Root != "" {
resolved.rootPath = context.Root
}
} else if context != nil && context.FS != nil {
namespace = context.FS.namespace
resolved.rootPath, resolved.basePath = context.Root, context.BaseDir
}
if namespace == nil || nilFilesystem(namespace.filesystem) || !fs.ValidPath(resolved.rootPath) || !fs.ValidPath(resolved.basePath) {
value := optionDiagnostic(CodeOptionsInvalid, "filesystem context is invalid")
return resolvedFilesystemContext{}, &value
}
resolved.native = namespace
if !containsNativePath(resolved.rootPath, resolved.basePath) || resolved.mainPath != "" && !containsNativePath(resolved.rootPath, resolved.mainPath) {
value := importDiagnostic(CodeImportOutsideRoot, "selected source and import base must stay inside the configuration root", nil)
return resolvedFilesystemContext{}, &value
}
return resolved, nil
}
func resolveHostFilesystemContext(source Source, context *FilesystemContext, main parsedSource, hostToken *namespaceToken) (resolvedFilesystemContext, *Diagnostic) {
if main.source == nil || main.document == nil {
value := importDiagnostic(CodeImportInvalid, "imports require a selected configuration source", nil)
return resolvedFilesystemContext{}, &value
}
resolved := resolvedFilesystemContext{hostToken: hostToken}
if source.kind == sourceFile {
if context != nil && context.BaseDir != "" {
value := optionDiagnostic(CodeOptionsInvalid, "file sources determine their own import base directory")
return resolvedFilesystemContext{}, &value
}
canonical := main.source.Path
if canonical == "" {
var err error
canonical, err = canonicalExistingPath(source.path)
if err != nil {
value := importDiagnostic(CodeImportInvalid, "selected source path could not be canonicalized", nil)
return resolvedFilesystemContext{}, &value
}
}
resolved.mainPath = canonical
resolved.basePath = filepath.Dir(canonical)
resolved.rootPath = resolved.basePath
if context != nil && context.Root != "" {
rootPath, err := canonicalExistingPath(context.Root)
if err != nil {
value := importDiagnostic(CodeImportInvalid, "configuration root could not be canonicalized", nil)
return resolvedFilesystemContext{}, &value
}
resolved.rootPath = rootPath
}
} else {
if context == nil || context.BaseDir == "" || context.Root == "" {
value := optionDiagnostic(CodeOptionsInvalid, "byte and reader imports require absolute base and root directories")
return resolvedFilesystemContext{}, &value
}
if !filepath.IsAbs(context.BaseDir) || !filepath.IsAbs(context.Root) {
value := optionDiagnostic(CodeOptionsInvalid, "byte and reader import base and root directories must be absolute")
return resolvedFilesystemContext{}, &value
}
var err error
resolved.basePath, err = canonicalExistingPath(context.BaseDir)
if err != nil {
value := importDiagnostic(CodeImportInvalid, "import base directory could not be canonicalized", nil)
return resolvedFilesystemContext{}, &value
}
resolved.rootPath, err = canonicalExistingPath(context.Root)
if err != nil {
value := importDiagnostic(CodeImportInvalid, "configuration root could not be canonicalized", nil)
return resolvedFilesystemContext{}, &value
}
}
if !containedPath(resolved.rootPath, resolved.basePath) || resolved.mainPath != "" && !containedPath(resolved.rootPath, resolved.mainPath) {
value := importDiagnostic(CodeImportOutsideRoot, "selected source and import base must stay inside the configuration root", nil)
return resolvedFilesystemContext{}, &value
}
return resolved, nil
}
func containsNativePath(root, name string) bool {
if !fs.ValidPath(name) || !fs.ValidPath(root) {
return false
}
return root == "." || name == root || strings.HasPrefix(name, root+"/")
}
func validateResolvedFilesystemDirectories(resolved resolvedFilesystemContext) *Diagnostic {
for _, directory := range []string{resolved.rootPath, resolved.basePath} {
var info fs.FileInfo
var err error
if resolved.native != nil {
info, err = fs.Stat(resolved.native.filesystem, directory)
} else {
info, err = os.Stat(directory)
}
if err != nil || !info.IsDir() {
value := importDiagnostic(CodeImportInvalid, "configuration root and import base must be directories", nil)
return &value
}
}
return nil
}
func openResolvedFilesystemAccess(resolved resolvedFilesystemContext) (*filesystemAccess, error) {
if resolved.native != nil {
access := newNativeAccess(resolved.native.filesystem, resolved.rootPath, resolved.native.token)
access.label = resolved.native.label
return access, nil
}
access, err := openHostAccess(resolved.rootPath)
if err != nil {
return nil, err
}
if resolved.hostToken != nil {
access.token = resolved.hostToken
}
return access, nil
}

View File

@@ -76,36 +76,22 @@ func acquireImportedInput(request importAcquisitionRequest, policy *acquisitionP
source := request.input.input.source
context := request.input.input.filesystem
main := request.main
if nativeContext(source, context) {
access, basePath, mainPath, diagnostic := nativeFilesystemAccess(source, context)
if diagnostic != nil {
return nil, sourceInfos(main.source), []Diagnostic{*diagnostic}
}
native := source.namespace
if native == nil && context != nil && context.FS != nil {
native = context.FS.namespace
}
return acquireImportedWithAccess(request, policy, state, tier, access, resolvedFilesystemContext{
native: native, hostToken: tier.hostToken, rootPath: access.rootPath,
basePath: basePath, mainPath: mainPath,
})
}
rootPath, basePath, mainPath, diagnostic := importFilesystem(source, context, main)
resolved, diagnostic := resolveFilesystemContext(source, context, main, tier.hostToken)
if diagnostic != nil {
return nil, sourceInfos(main.source), []Diagnostic{*diagnostic}
}
access, err := openHostAccess(rootPath)
if resolved.native == nil {
if diagnostic := validateResolvedFilesystemDirectories(resolved); diagnostic != nil {
return nil, sourceInfos(main.source), []Diagnostic{*diagnostic}
}
}
access, err := openResolvedFilesystemAccess(resolved)
if err != nil {
diagnostic := globFilesystemDiagnostic(err, "configuration root could not be opened", Location{})
diagnostic.Primary = nil
return nil, sourceInfos(main.source), []Diagnostic{diagnostic}
}
if tier.hostToken != nil {
access.token = tier.hostToken
}
return acquireImportedWithAccess(request, policy, state, tier, access, resolvedFilesystemContext{
hostToken: tier.hostToken, rootPath: rootPath, basePath: basePath, mainPath: mainPath,
})
return acquireImportedWithAccess(request, policy, state, tier, access, resolved)
}
func acquireImportedWithAccess(request importAcquisitionRequest, policy *acquisitionPolicy, loadState *acquisitionState, tier *tierAcquisitionState, access *filesystemAccess, resolved resolvedFilesystemContext) (*composedDocument, []SourceInfo, []Diagnostic) {