What problem are you trying to solve?
The maintainers agreed the general idea. This issue records the plan and scope.
extends accepts only a profile name or a registry ref (org/pack). It does not accept a file path. To share a base profile between project profiles, you must put the base in the same directory or in ~/.config/nono/profiles/.
- When nono exits with denials, it offers to save grants. It saves only to the top-level profile, or to a new user profile. It cannot save to a profile that the top-level profile extends.
- Bug: if you run
--profile ./path/to/profile.json, the save prompt cannot update that file. It creates a new user profile, and the new profile does not extend your file. The grants are then not used with your profile.
- Bug: the save writes the file again with
serde_json. This removes all JSONC comments and adds all default fields.
What would you like to see?
Phase 1: relative paths in extends
- An
extends entry that starts with ./ or ../ is a path.
- nono resolves the path from the canonical directory of the file that contains the entry.
org/pack stays a registry ref. A bare name keeps the current lookup order.
- Cycle detection uses the canonical path for path entries.
- A profile in the pack store must not use a path entry. nono rejects it with an error.
- A profile in
profile-drafts/ must not use a relative path entry, because profile promote moves the file. nono rejects it with an error.
- These callers must accept path entries:
load_profile_extends, package_status::walk_extends_chain, profile show/diff/validate, profile init --extends, why, and --extends on the CLI (relative to the current directory).
- Fix bug 3: when
--profile is a file path, the save prompt offers to update that file.
- Fix bug 4: save edits use the
cst feature of jsonc-parser (already a dependency). The edit adds only new entries. Comments and layout stay.
Phase 2: choose the save target on exit
Flow:
- The session ends with denials. nono builds the patch (no change).
- The user selects the items to grant or suppress (no change).
- nono gets the list of files in the resolved
extends chain, with the source of each file.
- nono removes these sources from the list:
- Pack store profiles. The pack verification fails if the file changes, and
nono pull replaces the file.
- Built-in profiles. They are not files.
- If the list is empty, nono offers to create a new user profile (current behaviour).
- If the list has one file, nono asks to update that file (current behaviour).
- If the list has more than one file, nono shows the list. The top-level profile is first and is the default. The bases follow in chain order. The last option is "new user profile".
- For a base profile, the prompt shows that the grant applies to all profiles that extend that base.
- nono writes all selected items to one file. (Selecting a target for each item is out of scope.)
Out of scope
- Absolute paths and
~/ paths in extends. Reasons:
- The use case is a shared base inside one project tree. Relative paths cover it.
- A base in the user profile directory is already available by bare name.
~/ adds a second way to do the same thing.
- Absolute and
~/ paths make a profile specific to one machine and one user. The profile fails when you share it in a repository.
~/ needs a home directory source. HOME is an environment variable, and nono treats environment variables as untrusted. This needs its own design.
- We can add them later without a breaking change, because nono rejects them now.
- A different save target for each item.
- Changes to the sandbox library or enforcement.
What have you tried instead?
- Put the base profile in the same directory as the child, and extend it by name (sibling lookup).
- Put the base profile in
~/.config/nono/profiles/, and extend it by name. This does not work for a base that is part of a project repository.
- After the save prompt, move grants to the base profile manually.
How is this blocking you?
It would be a nice improvement but I have a workaround
Additional context
Risks
- A path entry can point to any file that the user can read. This adds no new trust: the top-level profile can already grant the same access directly. The pack store restriction stops a pack from loading files outside the pack.
- A grant saved to a shared base applies to more profiles. The prompt in step 8 tells the user.
- A project profile can be in a git repository. A grant saved there can be committed. The prompt shows the full file path.
Tests
- Path resolution:
./, ../, symlinked directories, cycles through paths, missing file.
- Rejection: path entry in a pack store profile, relative entry in a draft.
- Save: update a path profile; keep JSONC comments; target list excludes packs and built-ins; default is the top-level profile.
This issue was drafted with help from Claude Code (AI agent).
What problem are you trying to solve?
The maintainers agreed the general idea. This issue records the plan and scope.
extendsaccepts only a profile name or a registry ref (org/pack). It does not accept a file path. To share a base profile between project profiles, you must put the base in the same directory or in~/.config/nono/profiles/.--profile ./path/to/profile.json, the save prompt cannot update that file. It creates a new user profile, and the new profile does not extend your file. The grants are then not used with your profile.serde_json. This removes all JSONC comments and adds all default fields.What would you like to see?
Phase 1: relative paths in
extendsextendsentry that starts with./or../is a path.org/packstays a registry ref. A bare name keeps the current lookup order.profile-drafts/must not use a relative path entry, becauseprofile promotemoves the file. nono rejects it with an error.load_profile_extends,package_status::walk_extends_chain,profile show/diff/validate,profile init --extends,why, and--extendson the CLI (relative to the current directory).--profileis a file path, the save prompt offers to update that file.cstfeature ofjsonc-parser(already a dependency). The edit adds only new entries. Comments and layout stay.Phase 2: choose the save target on exit
Flow:
extendschain, with the source of each file.nono pullreplaces the file.Out of scope
~/paths inextends. Reasons:~/adds a second way to do the same thing.~/paths make a profile specific to one machine and one user. The profile fails when you share it in a repository.~/needs a home directory source.HOMEis an environment variable, and nono treats environment variables as untrusted. This needs its own design.What have you tried instead?
~/.config/nono/profiles/, and extend it by name. This does not work for a base that is part of a project repository.How is this blocking you?
It would be a nice improvement but I have a workaround
Additional context
Risks
Tests
./,../, symlinked directories, cycles through paths, missing file.This issue was drafted with help from Claude Code (AI agent).