function cmd::identity::_rule() { local subcmd="${1:-show}" shift || true case "$subcmd" in assign) cmd::identity::_rule_assign "$@" ;; unassign) cmd::identity::_rule_unassign "$@" ;; show) cmd::identity::_rule_show "$@" ;; *) log::error "Unknown rule subcommand '${subcmd}'. Available: assign, unassign, show" return 1 ;; esac } function cmd::identity::_rule_assign() { local name="" rule="" while [[ $# -gt 0 ]]; do case "$1" in --name) name="$2"; shift 2 ;; --rule) rule="$2"; shift 2 ;; *) log::error "Unknown flag: $1"; return 1 ;; esac done [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; } [[ -z "$rule" ]] && { log::error "Missing required flag: --rule"; return 1; } identity::require_exists "$name" || return 1 rule::exists "$rule" || { log::error "Rule not found: ${rule}"; return 1; } local exit_code identity::add_rule "$name" "$rule" || exit_code=$? if [[ $exit_code -eq 2 ]]; then log::warn "Rule '${rule}' is already assigned to identity '${name}'" return 0 fi log::ok "Rule '${rule}' assigned to identity '${name}'" # Reapply rules if auto_apply local auto auto=$(identity::rule_flags "$name" "auto_apply") if [[ "$auto" != "false" ]]; then log::info "Reapplying rules for all peers in identity '${name}'..." identity::reapply_rules "$name" log::ok "Rules reapplied" fi # Warn about strict_rule if policy::strict_rule "$(identity::policy "$name")"; then log::warn "Strict rule is enabled for identity '${name}' — peer rules will not be additive" fi } function cmd::identity::_rule_unassign() { local name="" rule="" all=false while [[ $# -gt 0 ]]; do case "$1" in --name) name="$2"; shift 2 ;; --rule) rule="$2"; shift 2 ;; --all) all=true; shift ;; *) log::error "Unknown flag: $1"; return 1 ;; esac done [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; } identity::require_exists "$name" || return 1 if $all; then local rules rules=$(identity::rules "$name") if [[ -z "$rules" ]]; then log::warn "Identity '${name}' has no rules assigned" return 0 fi identity::clear_rules "$name" log::ok "All rules removed from identity '${name}'" cmd::identity::_reapply_after_unassign "$name" return 0 fi [[ -z "$rule" ]] && { log::error "Missing required flag: --rule (or use --all to remove all)" return 1 } identity::remove_rule "$name" "$rule" local exit_code=$? if [[ $exit_code -ne 0 ]]; then log::error "Rule '${rule}' is not assigned to identity '${name}'" return 1 fi log::ok "Rule '${rule}' removed from identity '${name}'" cmd::identity::_reapply_after_unassign "$name" } function cmd::identity::_rule_show() { local name="" while [[ $# -gt 0 ]]; do case "$1" in --name) name="$2"; shift 2 ;; *) log::error "Unknown flag: $1"; return 1 ;; esac done [[ -z "$name" ]] && { log::error "Missing required flag: --name"; return 1; } identity::require_exists "$name" || return 1 local rules policy strict auto rules=$(identity::rules "$name") policy=$(identity::policy "$name") strict=$(identity::rule_flags "$name" "strict_rule") auto=$(identity::rule_flags "$name" "auto_apply") echo "" ui::row "Identity" "$name" ui::row "Policy" "$policy" ui::row "Strict rule" "$(ui::bool "$strict")" ui::row "Auto apply" "$(ui::bool "$auto")" echo "" if [[ -z "$rules" ]]; then ui::row "Rules" "— none assigned" else printf " %-20s\n" "Rules:" while IFS= read -r rule_name; do [[ -z "$rule_name" ]] && continue printf " · %s\n" "$rule_name" done <<< "$rules" fi echo "" }