feat/policy: allow-rule placeholders for a value that precedes a further subcommand #105
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/subcommand-placeholders"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #52. An allow rule's subcommand list may now contain a placeholder segment spelled with a leading colon, for example issue, edit, :issue, title, so fj issue edit 50 title can be called. The tool is minted from the literal segments only as fj_issue_edit_title and each placeholder becomes a required schema parameter, typed number when its constraint says integer. The executor substitutes the value in place, before flags and before the double dash, so the value is not protected by the dash and gets its own guards, non-empty, no leading dash, no whitespace, no shell metacharacter, a strict shape of at most 256 characters, enforced by the policy layer and re-checked independently by the executor. Optional arg_constraints.placeholders narrows a value with the existing flag-constraint fields. Deny rules are checked exactly against the rule template as before and, for placeholder rules, again against the substituted path with a case-insensitive exact or prefix match, so deny issue, delete refuses allow issue, :x with x set to delete. That check matches literal text and cannot know a CLI's aliases, so the docs make a pattern allow-list the protection for an operand slot such as a kubectl resource and deny a backstop. Placeholder rules are operator-authored, the capability request path refuses them while the rules editor writes them under the same validation. Validation rejects a placeholder as the first segment, duplicate or malformed names, names clashing with a flag parameter or args, constraints for undeclared names, and two rules minting one tool name. Introspection and doctor drift skip placeholder rules so a template never reaches a help probe. The audit record carries the values. Two adversarial reviewer rounds with throwaway attack tests, flag injection at both layers, metacharacters and NUL, template leakage, argv ordering with two placeholders, name collisions, JSON number rendering, and the deny bypass found in round one and closed in round two. Design note at design/policy/subcommand-placeholders.md, docs in configuration.qmd, CHANGELOG Added bullet naming the remaining free-text obstacle for issue bodies. 🤖 Generated with Claude Code