Files
wehub-resource-sync bf9395e022
CI / results (push) Blocked by required conditions
CI / license-header (push) Has been skipped
CI / e2e-dry-run (push) Has been skipped
CI / e2e-live (push) Waiting to run
CI / fast-gate (push) Failing after 0s
Test PR Label Logic / test-pr-labels (push) Failing after 1s
Skill Format Check / check-format (push) Failing after 2s
CI / security (push) Failing after 5s
CI / unit-test (push) Has been skipped
CI / lint (push) Has been skipped
CI / script-test (push) Has been skipped
CI / deterministic-gate (push) Has been skipped
CI / coverage (push) Has been skipped
CI / deadcode (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 12:22:54 +08:00

137 lines
5.1 KiB
Go

// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package cmd
import (
"fmt"
"slices"
"github.com/spf13/cobra"
"github.com/larksuite/cli/errs"
"github.com/larksuite/cli/internal/cmdpolicy"
"github.com/larksuite/cli/internal/cmdutil"
"github.com/larksuite/cli/internal/core"
)
// pruneForStrictMode removes commands incompatible with the active strict mode.
func pruneForStrictMode(root *cobra.Command, mode core.StrictMode) {
pruneIncompatible(root, mode)
pruneEmpty(root)
}
// pruneIncompatible recursively replaces commands whose annotation declares
// identities incompatible with the forced identity. Commands without annotation are kept.
// Hidden stubs preserve direct execution so users get a strict-mode error instead
// of Cobra's generic "unknown flag" fallback from the parent command.
func pruneIncompatible(parent *cobra.Command, mode core.StrictMode) {
forced := string(mode.ForcedIdentity())
var toRemove []*cobra.Command
var toAdd []*cobra.Command
for _, child := range parent.Commands() {
ids := cmdutil.GetSupportedIdentities(child)
if ids != nil && !slices.Contains(ids, forced) {
toRemove = append(toRemove, child)
toAdd = append(toAdd, strictModeStubFrom(child, mode))
continue
}
pruneIncompatible(child, mode)
}
if len(toRemove) > 0 {
parent.RemoveCommand(toRemove...)
parent.AddCommand(toAdd...)
}
}
func strictModeStubFrom(child *cobra.Command, mode core.StrictMode) *cobra.Command {
// The denial annotations let the hook layer's populateInvocationDenial
// recognise this command as denied, so the Wrap chain is physically
// isolated (wrapRunE takes the DeniedByPolicy branch and calls the
// stub RunE directly). Without these, a plugin Wrapper registered
// against platform.All() could intercept and silently swallow the
// strict-mode error -- breaking strict-mode's "hard boundary" contract.
//
// Args + PersistentPreRunE overrides mirror cmdpolicy/apply.go::installDenyStub:
//
// - Args=ArbitraryArgs: with DisableFlagParsing the user's flags
// look like positional args; the original child's Args validator
// (e.g. cobra.NoArgs) would fire BEFORE RunE and produce a
// cobra usage error instead of our strict_mode envelope.
//
// - PersistentPreRunE no-op: cmd/auth/auth.go declares a parent
// PersistentPreRunE that returns external_provider when env
// credentials are set. Cobra's "first wins walking up" would
// pick auth's instead of our denial. A leaf-level no-op makes
// cobra stop here and proceed to the wrapped RunE.
//
// strict-mode keeps its short Message + independent Hint and wraps
// the CommandDeniedError as the Cause by hand; BuildDenialError
// would override Message with the CommandDeniedError.Error() long
// form.
stubMessage := fmt.Sprintf(
"strict mode is %q, only %s-identity commands are available",
mode, mode.ForcedIdentity())
const stubHint = "if the user explicitly wants to switch policy, see `lark-cli config strict-mode --help` (confirm with the user before switching; switching does NOT require re-bind)"
denial := cmdpolicy.Denial{
Layer: cmdpolicy.LayerStrictMode,
PolicySource: "strict-mode",
ReasonCode: "identity_not_supported",
Reason: stubMessage,
}
// Preserve the original command's annotations (risk_level,
// lark:supportedIdentities, cmdmeta.domain, ...) and help text so
// audit / compliance observers can still see what was denied.
// Stamp the denial annotations on top.
annotations := make(map[string]string, len(child.Annotations)+2)
for k, v := range child.Annotations {
annotations[k] = v
}
annotations[cmdpolicy.AnnotationDenialLayer] = cmdpolicy.LayerStrictMode
annotations[cmdpolicy.AnnotationDenialSource] = "strict-mode"
return &cobra.Command{
Use: child.Use,
Aliases: append([]string(nil), child.Aliases...),
Short: child.Short,
Long: child.Long,
Hidden: true,
DisableFlagParsing: true,
Args: cobra.ArbitraryArgs,
Annotations: annotations,
PersistentPreRunE: func(c *cobra.Command, _ []string) error {
c.SilenceUsage = true
return nil
},
RunE: func(c *cobra.Command, _ []string) error {
cd := cmdpolicy.CommandDeniedFromDenial(cmdpolicy.CanonicalPath(c), denial)
return errs.NewValidationError(errs.SubtypeFailedPrecondition, "%s", stubMessage).
WithHint("denied by %s policy (reason_code %s); %s", cd.Layer, cd.ReasonCode, stubHint).
WithCause(cd)
},
}
}
// pruneEmpty recursively removes group commands (no Run/RunE) that have
// no remaining subcommands after pruning. If only hidden stubs remain, keep
// the group hidden so direct execution still resolves to the stub path.
func pruneEmpty(parent *cobra.Command) {
var toRemove []*cobra.Command
for _, child := range parent.Commands() {
pruneEmpty(child)
if child.Run != nil || child.RunE != nil {
continue
}
switch {
case child.HasAvailableSubCommands():
case len(child.Commands()) > 0:
child.Hidden = true
default:
toRemove = append(toRemove, child)
}
}
if len(toRemove) > 0 {
parent.RemoveCommand(toRemove...)
}
}