Skip to content

gate github auth and harden deps/migrate/template commands; bump to dev3#36

Open
bsummers-tc wants to merge 8 commits into
ThreatConnect-Inc:develop-2from
bsummers-tc:develop-2
Open

gate github auth and harden deps/migrate/template commands; bump to dev3#36
bsummers-tc wants to merge 8 commits into
ThreatConnect-Inc:develop-2from
bsummers-tc:develop-2

Conversation

@bsummers-tc

Copy link
Copy Markdown
Contributor

No description provided.

added initial claude code configuration - WIP
Dependencies
- Raise runtime pins in pyproject.toml: arrow ~=1.4.0, black ~=26.5.1,
  inflection ~=0.5.1, isort ~=8.0.1, jmespath ~=1.1.0, paho-mqtt ~=2.1.0,
  pyaes ~=1.6.1, python-dateutil ~=2.9.0.post0, pyyaml ~=6.0.3, redis ~=8.0.0,
  requests ~=2.34.2, rich ~=15.0.0, semantic-version ~=2.10.0, typer ~=0.26.7,
  wrapt ~=2.2.1 (typer kept ~= to cap the major)
- Leave pydantic, pydantic-settings, debugpy, python-dotenv, tinydb, and
  fakeredis untouched
- dev group: switch bandit, pre-commit, pyupgrade, ruff, ty from ~= to >= and
  raise floors (bandit>=1.9.4, pre-commit>=4.6.0, pyupgrade>=3.21.2,
  ruff>=0.15.16, ty>=0.0.43)
- test group: switch pytest, pytest-cov, pytest-ordering to >= and raise
  pytest-cov to >=7.1.0

Build
- Regenerate uv.lock for the new constraints (black, isort 6->8, pytest-cov,
  rich 13->15, wrapt 1->2)

Submodules
- Bump app/config, pleb, requests_tc, and util pointers to their latest
  "linting and general cleanup" commits

Config
- Expand the Bash deny-list in .claude/settings.json to block git commit,
  push, pull, reset, rebase, merge, cherry-pick, clean, branch -d/-D/-m/-M,
  tag -d/-D, worktree remove/prune, and other history-rewriting operations
Deps
- Replace the shell-parsed `pip freeze` (subprocess shell=True) with a list-arg
  invocation (shell=False) in DepsCli.requirements_lock_contents, removing the
  command-injection surface (nosec B603 with justification)
- Run freeze via uv when available, else `python -m pip freeze --path`
- Hard-fail (Render.panel.failure) instead of writing an empty requirements.lock
  when the freeze returns no packages or a non-zero exit code
- Write the lock with a trailing newline (single fh.write) instead of an empty
  second write

Migrate
- Make `migrate` preview-by-default: writes are now gated behind `--apply`
  (alias `--update-code`); without it the command only previews and modifies
  no files
- Add `--no-prompt` for unattended/agent runs (apply every accepted change
  without interactive confirmation)
- Track and render a run summary (files scanned, changes proposed/applied,
  files changed) adapting text to preview vs apply mode
- Skip dot-directories (.git, .venv, .claude, ...) in addition to the named
  skip dirs; switch _skip_directories to a set and walk on directory parts
- Fix the failure log message to reference "tcex migrate" (was "tcex deps")

Template
- Add a `--authenticate` flag to `init`, `list`, and `update` that gates GitHub
  auth behind GITHUB_USER / GITHUB_PAT env vars (private forks / higher rate
  limit), threaded through TemplateCli
- Add `--no-prompt` to `update` for non-interactive runs: template-owned files
  are force-overwritten while locally-modified non-template files are preserved
  untouched and reported for manual review
- Planner.build accepts force_keys to reconcile template-owned files against the
  template sha256 unconditionally, before the last_commit short-circuit
- Planner.apply gains a no_prompt path and returns the list of preserved files
- Add TemplateCli._collect_template_file_keys to union template_files across the
  parent chain (normalized to POSIX keys, gitignore -> .gitignore)

Config
- Bump version 2.0.0-dev2 -> 2.0.0-dev3 (pyproject.toml, __metadata__.py)
- Add release notes for APP-5222/5299/5300/5301/5303
- Ignore tcex-app-templates-2 in .gitignore

Claude config
- Relocate enforcement hooks from .claude/scripts/ to .claude/hooks/ and repoint
  settings.json hook commands; drop the CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS env
- Add the tcex-plan-reviewer agent and expand tcex-orchestrator (guiding tenets,
  opt-in plan review, closing sections, never-stage policy)
- Update CLAUDE.md for the never-stage policy and the new hooks/ location

Tests
- Add tests/migrate/test_migrate_cli.py covering preview/apply/no-prompt and the
  run summary
- Add tests/template/test_gitignore_merge.py and test_template_files_force.py for
  force-overwrite of template-owned files
- Update template tests (conftest, test_template_abc, test_template_commands,
  test_merged_template) and the v2 templates fixture for the new behavior
- Update tests/deps/test_tcex_deps.py and app_1/requirements.txt for the hardened
  lock path
@bsummers-tc bsummers-tc self-assigned this Jun 20, 2026
…onfig and input validation

Template
- planner.py: replace the force_keys mechanism with a managed_only mode in
  Planner.build(); add _classify_managed_key() (managed-and-changed -> auto_update,
  managed-and-identical -> skip, non-managed -> skip, all removed keys -> skip so
  --managed never prompts or deletes); add 'managed' NotRequired bool to FileMeta;
  drop no_prompt/preserved from Planner.apply() (now returns None)
- template_cli.py: update() takes managed instead of no_prompt and passes
  managed_only; _build_merged_template() loads each parent manifest.json solely to
  stamp the per-file 'managed' flag (last_commit/sha256 stay re-hashed from the
  copied file); remove the now-unused _collect_template_file_keys()
- update.py: replace the --no-prompt option with --managed (silent, non-interactive
  update of only template-managed files; nothing deleted)

Run
- run.py / run_cli.py: resolve config via precedence -- explicit --config wins, else
  app_inputs.json, else a selection menu over app_inputs.d/*.json; read each
  candidate's description for the menu
- launch_playbook.py: add validate_inputs() to cross-check #App: input references
  against staged stage.kvstore keys -- referenced-but-unstaged is a hard failure
  (with a "did you mean" suggestion), staged-but-unreferenced is a warning; exclude
  output-declaring inputs via OUTPUT_VARIABLE_INPUTS (tc_playbook_out_variables)
- launch_abc.py: add _validate_env_variables() to fail fast on an undefined
  ${env.VAR} before substitution; use secrets.choice for the AES session key; redact
  the token value in the using-token setup log line; nosec B107 on tc_token default
- common_app_input_model.py: add optional description field to CommonAppInputModel

App Inputs
- app_input_cli.py / app_input.py: build an app_inputs.d/<slug>.json config from the
  App's install.json; add --name/--description options; _slugify_name() rejects names
  that would escape app_inputs.d/; write_output_file() writes under app_inputs.d/

Package
- package_cli.py: exclude the local app_inputs.d/ directory from packaged output

Render
- render.py: add the shared ${env.NAME} placeholder regex and a table_app_inputs_d()
  renderer for the multi-config selection menu

Tests
- add tests/run (test_run config resolution, test_validate_env ${env.VAR},
  test_validate_inputs kvstore cross-check), tests/app_input, and tests/package
- add tests/template/test_managed.py covering managed-mode plan classification and
  apply; remove obsolete test_template_files_force.py (force_keys behavior); trim
  test_template_commands.py and test_gitignore_merge.py of removed force_keys/
  no_prompt paths

Fixtures / Scripts
- add .claude/scripts/build_template_fixture.py to rebuild the GitHub-style fixture
  from the templates repo under a single tcex-app-templates-2/ wrapper (dry-run by
  default, --commit to write)
- rebuild tests/template/fixtures/tcex-app-templates-v2.zip from the latest templates
  repo with the correct single wrapper and per-file 'managed' flags (was rooted at a
  leaked absolute path)

Docs / Config
- release_notes.md: reword APP-5299 for --managed
- .claude/agents/tcex-orchestrator.md: expand the orchestrator tools list
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant