This document records the internal package audit findings and the agreed corrections. It is a planning document only; implementation belongs in a later pass.
Do not collapse packages merely to reduce the number of directories. Prefer targeted cleanup where a boundary is unclear, duplicated, or security-sensitive.
`internal/adapter/http` accepts `file` input references and maps them directly to `domain.ArtifactRef`. `internal/artifact` then reads `ref.URI` with `os.ReadFile`. Because `serve` has no built-in authentication, an HTTP caller can cause the server process to read arbitrary local files accessible to it.
Keep HTTP file inputs because they are a core use case, but require an explicit allowlisted artifact root for HTTP file reads and enforce path containment before reading.
1. Add an HTTP/server artifact root setting at the app wiring layer.
- Prefer a config field such as `server.artifact_root` or a clearly named top-level field such as `artifact_root`.
- Add the matching CLI `serve` override only if it fits existing config/CLI precedence patterns.
- The setting should apply to HTTP `serve` only; do not change CLI `run`/`render` file input behavior.
2. Introduce an artifact reader mode that restricts file reads to the configured root.
- Resolve the configured root with `filepath.Abs` and `filepath.Clean`.
- Resolve each requested file path against the root.
- Reject paths that escape the root, including `..` traversal and absolute paths outside the root.
- Use `filepath.Rel` or equivalent path-containment checks; do not rely on string-prefix checks alone.
- Consider rejecting symlink escapes if the threat model includes untrusted writable artifact roots. If symlinks are allowed, document that the root must not be writable by untrusted users.
3. Preserve inline input behavior.
4. Decide startup behavior:
- Recommended: if HTTP `serve` accepts `file` refs, `artifact_root` must be configured before file refs are allowed.
- If no root is configured, HTTP `file` refs should return `400 artifact_read_failed` or a more specific `400 artifact_not_allowed`; inline refs should continue to work.
5. Keep public Go API and CLI behavior unchanged unless explicitly using the restricted artifact reader for HTTP wiring.
Prompt and profile repositories duplicate YAML discovery and `fs.FS` path handling. `internal/filecatalog` currently handles only OS directory walking, while `promptdef` and `profile` each carry similar `fs.FS` walking, file extension, path cleaning, display path, and stem logic.
Expand `internal/filecatalog` into the shared YAML catalog/path helper for both OS directories and `fs.FS` roots. This is preferable to deleting it because both prompt and profile loaders need the same behavior.
`StandardValidator.Validate` and `FSValidator.Validate` duplicate most validation-mode logic. The meaningful difference is how JSON Schema documents are loaded and compiled.
Extract shared validation-mode control flow and isolate schema loading behind a small internal function/interface. Keep the public package boundary unchanged.
`domain.RunResult.Error` and `domain.RunMetadata` appear unused. They make the central domain package broader than necessary and can confuse future contributors about intended result/error handling.
Keep these package boundaries. The interfaces describe real use-case seams and are imported by adapters and `internal/usecase`. Do not merge these packages solely to remove small files.
1. No code change is required for package consolidation.
2. If a package is already being edited, it is acceptable to move an interface into a nearby implementation file only when that improves readability and does not blur ownership.
3. Keep `internal/domain` free of adapter implementation details.
4. Keep `internal/usecase` dependent on interfaces rather than concrete filesystem/model implementations.