code-context-control 2.86.0__tar.gz → 2.88.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {code_context_control-2.86.0/code_context_control.egg-info → code_context_control-2.88.2}/PKG-INFO +1 -1
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/c3.py +128 -9
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/commands/parser.py +15 -2
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/guide/credentials.html +80 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hook_pretool_enforce.py +2 -1
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_server.py +33 -2
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/drill_panel.js +2 -2
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/hub_credentials.js +227 -23
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/mcp_server.py +18 -6
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/server.py +34 -10
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/credentials.py +105 -4
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/shell.py +52 -8
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/components/credentials.js +251 -23
- {code_context_control-2.86.0 → code_context_control-2.88.2/code_context_control.egg-info}/PKG-INFO +1 -1
- {code_context_control-2.86.0 → code_context_control-2.88.2}/code_context_control.egg-info/SOURCES.txt +2 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/oracle_server.py +4 -4
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/local_session.py +28 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/mobile_api.py +29 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/pyproject.toml +1 -1
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/claude_md.py +1 -1
- code_context_control-2.88.2/services/cred_telemetry.py +303 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/credential_store.py +399 -23
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/parser.py +24 -0
- code_context_control-2.88.2/tests/test_cred_telemetry.py +189 -0
- code_context_control-2.88.2/tests/test_credential_store.py +525 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_credentials_routes.py +82 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_credentials_tool.py +96 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_delegate_cascade.py +52 -1
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_hub_credentials_routes_write.py +54 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_mobile_security_api.py +32 -1
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_oracle_session_bootstrap.py +101 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_shell_creds.py +85 -2
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_validate.py +57 -0
- code_context_control-2.86.0/tests/test_credential_store.py +0 -270
- {code_context_control-2.86.0 → code_context_control-2.88.2}/LICENSE +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/README.md +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/__init__.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/_hook_utils.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/commands/__init__.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/commands/common.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/docs.html +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/edits.html +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/guide/access.html +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/guide/bitbucket.html +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/guide/getting-started.html +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/guide/index.html +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/guide/masking.html +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/guide/oracle.html +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/guide/shared.css +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/guide/tools.html +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/guide/workflow.html +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hook_access_guard.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hook_artifact.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hook_auto_snapshot.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hook_c3_signal.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hook_c3read.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hook_dispatch.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hook_edit_ledger.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hook_edit_unlock.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hook_filter.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hook_ghost_files.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hook_prompt_recall.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hook_read.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hook_session_stats.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hook_terse_advisor.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/app.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/add_project.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/config_editor.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/drill_artifacts.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/drill_health.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/drill_subprojects.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/drill_tasks.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/drill_views.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/global_search.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/hub_ci.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/hub_enforcement.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/hub_locks.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/mcp_manager.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/modals.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/project_card.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/project_tree.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/session_drawer.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/settings_modal.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/sidebar.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/summary_bar.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/task_board.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/toasts.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/topbar.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/state.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui.html +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/mcp_proxy.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/progress.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/__init__.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/_grants.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/_helpers.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/agent.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/artifacts.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/bitbucket.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/ci.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/compress.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/delegate.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/edit.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/edit_verify.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/edits.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/federate.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/filter.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/impact.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/jira.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/locks.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/memory.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/override.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/project.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/read.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/search.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/session.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/status.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/tasks.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/tools/validate.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/api.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/app.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/components/access.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/components/bitbucket.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/components/chat.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/components/dashboard.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/components/edits.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/components/enforcement.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/components/instructions.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/components/jira.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/components/memory.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/components/sessions.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/components/settings.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/components/sidebar.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/components/tasks.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/icons.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/pm_shared.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/shared.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui/theme.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui.html +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui_legacy.html +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/cli/ui_nano.html +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/code_context_control.egg-info/dependency_links.txt +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/code_context_control.egg-info/entry_points.txt +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/code_context_control.egg-info/requires.txt +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/code_context_control.egg-info/top_level.txt +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/core/__init__.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/core/config.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/core/ide.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/core/mcp_toml.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/core/web_security.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/__init__.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/config.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/mcp_oracle.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/oracle_ui.html +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/__init__.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/activity_reporter.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/api_auth.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/c3_bridge.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/chat_engine.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/chat_poll.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/chat_store.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/cross_memory.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/discovery_audit.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/federated_graph.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/health_checker.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/insight_engine.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/memory_reader.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/memory_writer.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/project_scanner.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/review_agent.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/tool_executor.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/services/tool_registry.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/activity.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/agents.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/app.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/busy.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/chat/conversations.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/chat/input.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/chat/markdown.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/chat/send.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/chat/stream_renderer.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/chat/toolbar.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/core.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/crossgraph.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/header.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/insights.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/projects.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/qrcode.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/settings.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/suggestions.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/oracle/ui/theme_tabs.js +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/__init__.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/access_guard.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/access_telemetry.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/activity_log.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/agent_base.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/agent_locks.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/agents.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/artifact_defs.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/artifact_store.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/auto_memory.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/bench/__init__.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/bench/external/__init__.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/bench/external/aider_polyglot.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/bench/external/swe_bench.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/benchmark_dashboard.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/bitbucket_client.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/bitbucket_credentials.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/ci_act.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/ci_cache.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/ci_expr.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/ci_failures.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/ci_github.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/ci_impact.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/ci_intel.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/ci_runner.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/ci_workflow.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/circuit_breaker.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/compressor.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/context_snapshot.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/conversation_store.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/doc_index.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/e2e_benchmark.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/e2e_evaluator.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/e2e_tasks.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/edit_ledger.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/embedding_index.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/enforcement_policy.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/error_reporting.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/file_memory.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/git_context.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/hub_service.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/indexer.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/jira_client.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/jira_cloud.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/jira_credentials.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/jira_data_center.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/jira_links.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/mask_activation.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/mask_mirror.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/mask_presets.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/memory.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/memory_consolidator.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/memory_distiller.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/memory_graph.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/memory_grounder.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/memory_queue.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/memory_scorer.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/metrics.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/notifications.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/ollama_bridge.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/ollama_client.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/ollama_credentials.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/output_filter.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/override_grants.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/override_policy.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/override_requests.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/override_wake.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/project_manager.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/project_runtime.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/protocol.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/proxy_state.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/repo_map.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/retention.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/retrieval_broker.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/router.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/runtime.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/scanner.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/session_benchmark.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/session_manager.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/session_preloader.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/subprojects.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/task_store.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/telemetry.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/text_index.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/time_tracker.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/tool_classifier.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/transcript_index.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/validation_cache.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/vector_store.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/watcher.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/services/win_subprocess.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/setup.cfg +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_access_builtin_optout.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_access_guard.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_access_guard_meta.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_access_guard_shell_project.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_access_guard_surfaces.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_access_guard_wiring.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_activity_reporter.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_agent_locks.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_aider_polyglot.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_antigravity_transition.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_artifact_store.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_artifact_tool.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_bitbucket_cli_smoke.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_bitbucket_client.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_bitbucket_config_fallback.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_bitbucket_credentials.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_bitbucket_tool.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_c3_bridge_project_artifacts.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_c3_shell.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_chat_poll.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_ci_act.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_ci_cache.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_ci_expr.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_ci_impact.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_ci_intel.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_ci_runner.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_ci_workflow.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_circuit_breaker.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_claude_md_merge.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_cli_smoke.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_compressor_large_file.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_creds_cli_smoke.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_delegate_version_probe.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_e2e_benchmark.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_edit_ledger_deadline.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_edit_ledger_hook.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_edit_locking.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_edit_normalization.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_edit_verify.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_embedding_index_deadlock.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_enforcement_flip.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_enforcement_policy.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_enforcement_routes.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_federated_graph.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_filter_backoff.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_ghost_files.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_ghost_generation.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_git_branch_awareness.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_hook_access_guard.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_hook_codex_compat.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_hook_dispatch.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_hook_pretool_enforce.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_hook_prompt_recall.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_hook_smoke.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_hook_state.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_hook_utf8_stdio.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_hub_credentials_route.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_hub_enforcement_routes.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_hub_inspect_api.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_hub_locks_routes.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_hub_server_smoke.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_hub_subproject_links.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_ide_workflow_adaptation.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_init_scan.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_install_mcp_entrypoint.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_jira_cli_smoke.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_jira_client.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_jira_config_fallback.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_jira_credentials.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_jira_links.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_jira_routes.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_jira_tool.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_lazy_store_init.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_mask_guard.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_mask_routes.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_mask_surfaces.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_mcp_host_guard.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_mcp_memory_timeout.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_mcp_server_smoke.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_mcp_toml.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_memory_distiller.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_memory_graph_api.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_memory_queue.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_memory_system.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_mobile_api.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_mobile_extras.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_mobile_override_routes.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_no_stale_model_pins.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_notification_dedup.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_notification_discipline.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_ollama_credentials.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_oracle_api_auth.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_oracle_apikey_api.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_oracle_c3_bridge.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_oracle_chat_engine.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_oracle_chat_store.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_oracle_discovery_api.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_oracle_discovery_audit.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_oracle_local_auth.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_oracle_ollama_bridge.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_oracle_scanner_cache.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_oracle_security_fixes.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_oracle_subproject_awareness.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_oracle_ui_bundle.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_output_filter.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_override_grants.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_override_grants_mcp.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_override_requests.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_override_wake.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_permissions.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_pm_api.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_project_manager.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_project_manager_merge.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_project_tool.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_read_coercion.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_read_edit_parity.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_related_facts.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_repo_map.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_response_boilerplate.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_retention.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_review_digest.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_service_durability.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_session_benchmark.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_session_budget.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_shell_robustness.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_subproject_exclusion.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_subproject_federation.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_subprojects.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_swe_bench.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_task_store.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_task_tool.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_time_tracker.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_token_telemetry.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_tool_registry.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_upgrade_and_version.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_vault_write_guard.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_version_sync.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_web_security.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tests/test_windows_reliability.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/__init__.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/backend.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/main.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/screens/__init__.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/screens/benchmark_view.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/screens/claudemd_view.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/screens/compress_view.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/screens/index_view.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/screens/init_view.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/screens/mcp_view.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/screens/optimize_view.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/screens/pipe_view.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/screens/projects_view.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/screens/search_view.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/screens/session_view.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/screens/stats.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/screens/ui_view.py +0 -0
- {code_context_control-2.86.0 → code_context_control-2.88.2}/tui/theme.tcss +0 -0
{code_context_control-2.86.0/code_context_control.egg-info → code_context_control-2.88.2}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-context-control
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.88.2
|
|
4
4
|
Summary: Local MCP code-intelligence for AI coding tools: surgical search/read/edit, agent-config version history, path-level access + masking guards, and a multi-project hub.
|
|
5
5
|
Author-email: Dimitri Tselenchuk <dtselenc@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -92,7 +92,7 @@ console = Console() if HAS_RICH else None
|
|
|
92
92
|
# Config
|
|
93
93
|
CONFIG_DIR = ".c3"
|
|
94
94
|
CONFIG_FILE = ".c3/config.json"
|
|
95
|
-
__version__ = "2.
|
|
95
|
+
__version__ = "2.88.2"
|
|
96
96
|
|
|
97
97
|
|
|
98
98
|
def _compress_file_cli(compressor, path, mode="smart", **kw):
|
|
@@ -5899,7 +5899,7 @@ def cmd_creds(args):
|
|
|
5899
5899
|
"""Credential vault management (global + per-project scopes)."""
|
|
5900
5900
|
sub = getattr(args, "creds_cmd", None)
|
|
5901
5901
|
if not sub:
|
|
5902
|
-
print("Usage: c3 creds {set,get,list,rm,import} [args]")
|
|
5902
|
+
print("Usage: c3 creds {set,get,list,rm,import,usage} [args]")
|
|
5903
5903
|
return
|
|
5904
5904
|
|
|
5905
5905
|
project_path = getattr(args, "project_path", ".") or "."
|
|
@@ -5914,6 +5914,8 @@ def cmd_creds(args):
|
|
|
5914
5914
|
_creds_cmd_rm(args, project_path)
|
|
5915
5915
|
elif sub == "import":
|
|
5916
5916
|
_creds_cmd_import(args, project_path)
|
|
5917
|
+
elif sub == "usage":
|
|
5918
|
+
_creds_cmd_usage(args, project_path)
|
|
5917
5919
|
else:
|
|
5918
5920
|
print(f"Unknown creds subcommand: {sub}")
|
|
5919
5921
|
|
|
@@ -5928,6 +5930,9 @@ def _creds_entry_line(name: str, entry: dict) -> str:
|
|
|
5928
5930
|
f"{name:<24} {entry.get('scope', '?'):<8} {entry.get('type', 'token'):<10}"
|
|
5929
5931
|
f" len={entry.get('value_len', '?')}",
|
|
5930
5932
|
]
|
|
5933
|
+
display = entry.get("display") or {}
|
|
5934
|
+
if display:
|
|
5935
|
+
parts.append(" ".join(str(v) for v in display.values() if v))
|
|
5931
5936
|
if entry.get("env_var"):
|
|
5932
5937
|
parts.append(f"env_var={entry['env_var']}")
|
|
5933
5938
|
if flags:
|
|
@@ -5937,16 +5942,49 @@ def _creds_entry_line(name: str, entry: dict) -> str:
|
|
|
5937
5942
|
return " ".join(parts)
|
|
5938
5943
|
|
|
5939
5944
|
|
|
5945
|
+
_CREDS_HIDDEN_FIELDS = {"number", "cvc", "ssn"} # prompted via getpass
|
|
5946
|
+
|
|
5947
|
+
|
|
5948
|
+
def _creds_prompt_structured(name: str, ctype: str) -> str:
|
|
5949
|
+
"""Interactive per-field prompt for a structured entry; returns JSON.
|
|
5950
|
+
Sensitive fields use a hidden prompt; empty optional fields are skipped."""
|
|
5951
|
+
import getpass
|
|
5952
|
+
import json as _json
|
|
5953
|
+
|
|
5954
|
+
from services import credential_store as cred_store
|
|
5955
|
+
|
|
5956
|
+
required, optional = cred_store.schema_fields(ctype)
|
|
5957
|
+
print(f"Enter {ctype} fields for '{name}' "
|
|
5958
|
+
"(optional fields: press Enter to skip):")
|
|
5959
|
+
fields: dict = {}
|
|
5960
|
+
for fname in list(required) + list(optional):
|
|
5961
|
+
tag = "" if fname in required else " (optional)"
|
|
5962
|
+
if fname in _CREDS_HIDDEN_FIELDS:
|
|
5963
|
+
raw = getpass.getpass(f" {fname}{tag}: ")
|
|
5964
|
+
else:
|
|
5965
|
+
raw = input(f" {fname}{tag}: ")
|
|
5966
|
+
if raw.strip():
|
|
5967
|
+
fields[fname] = raw.strip()
|
|
5968
|
+
return _json.dumps(fields)
|
|
5969
|
+
|
|
5970
|
+
|
|
5940
5971
|
def _creds_cmd_set(args, project_path: str) -> None:
|
|
5941
5972
|
import getpass
|
|
5942
5973
|
|
|
5943
5974
|
from services import credential_store as cred_store
|
|
5944
5975
|
|
|
5976
|
+
ctype = getattr(args, "ctype", "token") or "token"
|
|
5945
5977
|
value = getattr(args, "value", "") or ""
|
|
5946
5978
|
if getattr(args, "stdin", False):
|
|
5947
5979
|
value = sys.stdin.read().rstrip("\n")
|
|
5948
5980
|
if not value:
|
|
5949
|
-
|
|
5981
|
+
if ctype in cred_store.STRUCTURED_TYPES:
|
|
5982
|
+
value = _creds_prompt_structured(args.name, ctype)
|
|
5983
|
+
if value == "{}":
|
|
5984
|
+
print("Cancelled -- no fields entered.")
|
|
5985
|
+
return
|
|
5986
|
+
else:
|
|
5987
|
+
value = getpass.getpass(f"Value for {args.name}: ")
|
|
5950
5988
|
if not value:
|
|
5951
5989
|
print("Cancelled -- value required.")
|
|
5952
5990
|
return
|
|
@@ -5956,7 +5994,7 @@ def _creds_cmd_set(args, project_path: str) -> None:
|
|
|
5956
5994
|
args.name, value,
|
|
5957
5995
|
scope=scope, project_path=project_path,
|
|
5958
5996
|
description=getattr(args, "desc", "") or "",
|
|
5959
|
-
ctype=
|
|
5997
|
+
ctype=ctype,
|
|
5960
5998
|
env_var=getattr(args, "env_var", "") or "",
|
|
5961
5999
|
agent_readable=bool(getattr(args, "agent_readable", False)),
|
|
5962
6000
|
inject=bool(getattr(args, "inject", False)),
|
|
@@ -5971,6 +6009,19 @@ def _creds_cmd_set(args, project_path: str) -> None:
|
|
|
5971
6009
|
"into its context and transcripts.")
|
|
5972
6010
|
|
|
5973
6011
|
|
|
6012
|
+
def _creds_count_show(refs, project_path: str) -> None:
|
|
6013
|
+
"""Count a terminal --show like any other use: state counter + history."""
|
|
6014
|
+
from services import credential_store as cred_store
|
|
6015
|
+
try:
|
|
6016
|
+
cred_store.touch_last_used(
|
|
6017
|
+
sorted({str(r).partition(".")[0] for r in refs}), project_path)
|
|
6018
|
+
from services import cred_telemetry as ct
|
|
6019
|
+
ct.record_use(refs, project_path=project_path,
|
|
6020
|
+
action=ct.ACTION_CLI_SHOW, surface="cli")
|
|
6021
|
+
except Exception:
|
|
6022
|
+
pass
|
|
6023
|
+
|
|
6024
|
+
|
|
5974
6025
|
def _creds_cmd_get(args, project_path: str) -> None:
|
|
5975
6026
|
from services import credential_store as cred_store
|
|
5976
6027
|
|
|
@@ -5981,11 +6032,46 @@ def _creds_cmd_get(args, project_path: str) -> None:
|
|
|
5981
6032
|
print(_creds_entry_line(args.name, entry))
|
|
5982
6033
|
print(f"storage={entry.get('storage', 'keyring')} "
|
|
5983
6034
|
f"created={entry.get('created', '?')} updated={entry.get('updated', '?')}")
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
if
|
|
5987
|
-
|
|
5988
|
-
print(
|
|
6035
|
+
stype = cred_store.structured_type(args.name, project_path=project_path)
|
|
6036
|
+
field = (getattr(args, "field", "") or "").strip()
|
|
6037
|
+
if not stype:
|
|
6038
|
+
fp = cred_store.fingerprint(args.name, project_path=project_path)
|
|
6039
|
+
print(f"fingerprint={fp or 'unresolvable'}")
|
|
6040
|
+
if field:
|
|
6041
|
+
print(f"[error] '{args.name}' is not structured -- --field does not apply")
|
|
6042
|
+
return
|
|
6043
|
+
if getattr(args, "show", False):
|
|
6044
|
+
value = cred_store.get_value(args.name, project_path=project_path)
|
|
6045
|
+
print(value if value is not None
|
|
6046
|
+
else "[error] value missing from store")
|
|
6047
|
+
if value is not None:
|
|
6048
|
+
_creds_count_show([args.name], project_path)
|
|
6049
|
+
return
|
|
6050
|
+
print(f"fields: {', '.join(entry.get('fields') or []) or 'none recorded'}")
|
|
6051
|
+
if not getattr(args, "show", False):
|
|
6052
|
+
if field:
|
|
6053
|
+
print("[hint] add --show to print the field value")
|
|
6054
|
+
return
|
|
6055
|
+
# --show: the deliberate human read-back path (terminal only; the wire
|
|
6056
|
+
# never carries these values). Counted as usage like any other reveal.
|
|
6057
|
+
if field:
|
|
6058
|
+
value = cred_store.get_value(args.name, project_path=project_path,
|
|
6059
|
+
field=field)
|
|
6060
|
+
if value is None:
|
|
6061
|
+
print(f"[error] no field '{field}' on '{args.name}'")
|
|
6062
|
+
return
|
|
6063
|
+
print(value)
|
|
6064
|
+
_creds_count_show([f"{args.name}.{field}"], project_path)
|
|
6065
|
+
else:
|
|
6066
|
+
fields = cred_store.get_structured_fields(
|
|
6067
|
+
args.name, project_path=project_path)
|
|
6068
|
+
if fields is None:
|
|
6069
|
+
print("[error] value missing from store")
|
|
6070
|
+
return
|
|
6071
|
+
width = max(len(k) for k in fields)
|
|
6072
|
+
for key in sorted(fields):
|
|
6073
|
+
print(f"{key:<{width}} {fields[key]}")
|
|
6074
|
+
_creds_count_show([args.name], project_path)
|
|
5989
6075
|
|
|
5990
6076
|
|
|
5991
6077
|
def _creds_cmd_list(args, project_path: str) -> None:
|
|
@@ -6039,6 +6125,39 @@ def _creds_cmd_import(args, project_path: str) -> None:
|
|
|
6039
6125
|
"(use --overwrite to replace)")
|
|
6040
6126
|
|
|
6041
6127
|
|
|
6128
|
+
def _creds_cmd_usage(args, project_path: str) -> None:
|
|
6129
|
+
import json as _json
|
|
6130
|
+
|
|
6131
|
+
from services import cred_telemetry as ct
|
|
6132
|
+
|
|
6133
|
+
name = getattr(args, "name", "") or ""
|
|
6134
|
+
limit = max(1, int(getattr(args, "limit", 20) or 20))
|
|
6135
|
+
agg = ct.aggregate(project_path, name=name)
|
|
6136
|
+
recent = ct.search_events(project_path, name=name, limit=limit)
|
|
6137
|
+
if getattr(args, "as_json", False):
|
|
6138
|
+
print(_json.dumps({"aggregate": agg, "recent": recent}, indent=2))
|
|
6139
|
+
return
|
|
6140
|
+
if not agg["total"]:
|
|
6141
|
+
target = f" for '{name}'" if name else ""
|
|
6142
|
+
print(f"No recorded credential uses{target} yet.")
|
|
6143
|
+
return
|
|
6144
|
+
surf = " ".join(f"{s}:{c}" for s, c in sorted(agg["by_surface"].items()))
|
|
6145
|
+
print(f"{agg['total']} use(s) across {len(agg['rows'])} credential(s)"
|
|
6146
|
+
f" [{surf}]")
|
|
6147
|
+
for row in agg["rows"]:
|
|
6148
|
+
fields = f" fields: {', '.join(row['fields'])}" if row["fields"] else ""
|
|
6149
|
+
print(f" {row['name']:<24} {row['hits']:>4}x last {row['last_ts'] or '?'}"
|
|
6150
|
+
f" projects={row['projects']}{fields}")
|
|
6151
|
+
print(f"recent (newest first, {len(recent['events'])}"
|
|
6152
|
+
f"/{recent['matched']}):")
|
|
6153
|
+
for e in recent["events"]:
|
|
6154
|
+
ref = e["name"] + (f".{e['field']}" if e.get("field") else "")
|
|
6155
|
+
exit_part = f" exit={e['exit']}" if "exit" in e else ""
|
|
6156
|
+
cmd_part = f" {e['cmd']}" if e.get("cmd") else ""
|
|
6157
|
+
print(f" {e.get('ts', '?')} {e.get('action', '?'):<10} {ref:<28}"
|
|
6158
|
+
f" [{e.get('surface', '?')}]{exit_part}{cmd_part}")
|
|
6159
|
+
|
|
6160
|
+
|
|
6042
6161
|
def cmd_ci(args):
|
|
6043
6162
|
"""AgentCI entry point — exits with the finding.
|
|
6044
6163
|
|
|
@@ -417,9 +417,14 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
417
417
|
"set", help="Create or update a credential (value via hidden prompt)"
|
|
418
418
|
)
|
|
419
419
|
cr_set.add_argument("name", help="Entry name (env-var safe: [A-Za-z_][A-Za-z0-9_]*)")
|
|
420
|
-
cr_set.add_argument("--value", default="", help="Secret value (prompted via getpass if omitted — preferred)")
|
|
420
|
+
cr_set.add_argument("--value", default="", help="Secret value (prompted via getpass if omitted — preferred). Structured types take a JSON object of fields")
|
|
421
421
|
cr_set.add_argument("--stdin", action="store_true", help="Read the value from stdin (piped/multiline values)")
|
|
422
|
-
cr_set.add_argument("--type", dest="ctype",
|
|
422
|
+
cr_set.add_argument("--type", dest="ctype",
|
|
423
|
+
choices=["token", "env", "multiline",
|
|
424
|
+
"address", "identity", "card"],
|
|
425
|
+
default="token",
|
|
426
|
+
help="Entry type; address/identity/card are structured "
|
|
427
|
+
"(field payload, inject-only, never revealable to the agent)")
|
|
423
428
|
cr_set.add_argument("--desc", default="", help="Human description shown in list/UI")
|
|
424
429
|
cr_set.add_argument("--env-var", default="", help="Env var name used at injection (default: entry name)")
|
|
425
430
|
cr_set.add_argument("--agent-readable", action="store_true", help="Allow the agent to reveal the decoded value into its context (default: injection-only)")
|
|
@@ -432,6 +437,7 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
432
437
|
cr_get = creds_subs.add_parser("get", help="Show entry metadata (masked; --show prints the value)")
|
|
433
438
|
cr_get.add_argument("name")
|
|
434
439
|
cr_get.add_argument("--show", action="store_true", help="Print the decoded value to the terminal")
|
|
440
|
+
cr_get.add_argument("--field", default="", help="For structured entries: limit --show to one field (e.g. number)")
|
|
435
441
|
cr_get.add_argument("--path", dest="project_path", default=".", help="Project directory (default: current)")
|
|
436
442
|
|
|
437
443
|
cr_list = creds_subs.add_parser("list", help="List credentials visible to this project")
|
|
@@ -448,6 +454,13 @@ def build_parser(version: str, parse_cli_ide_arg):
|
|
|
448
454
|
cr_import.add_argument("--overwrite", action="store_true", help="Replace entries already registered in the target scope")
|
|
449
455
|
cr_import.add_argument("--path", dest="project_path", default=".", help="Project directory (default: current)")
|
|
450
456
|
|
|
457
|
+
cr_usage = creds_subs.add_parser(
|
|
458
|
+
"usage", help="Usage history — when, where, and how often credentials were used")
|
|
459
|
+
cr_usage.add_argument("name", nargs="?", default="", help="Limit to one credential (default: all)")
|
|
460
|
+
cr_usage.add_argument("--limit", type=int, default=20, help="Recent events to show (default: 20)")
|
|
461
|
+
cr_usage.add_argument("--json", dest="as_json", action="store_true", help="Emit raw JSON")
|
|
462
|
+
cr_usage.add_argument("--path", dest="project_path", default=".", help="Project directory (default: current)")
|
|
463
|
+
|
|
451
464
|
# ── Agent Locks (docs/agent-locks.md) ───────────────────────────────
|
|
452
465
|
# force-release is human-only: it bumps the fencing counter so a holder
|
|
453
466
|
# that comes back is stale by construction. Agents get c3_locks instead,
|
|
@@ -105,11 +105,13 @@
|
|
|
105
105
|
<a href="#storage" class="sidebar-link"><span class="icon">🗄️</span> Where values live</a>
|
|
106
106
|
<a href="#scopes" class="sidebar-link"><span class="icon">🌍</span> Scopes & overriding</a>
|
|
107
107
|
<a href="#agent-use" class="sidebar-link"><span class="icon">🤖</span> How agents use them</a>
|
|
108
|
+
<a href="#structured" class="sidebar-link"><span class="icon">💳</span> Structured kinds</a>
|
|
108
109
|
<a href="#exposure" class="sidebar-link"><span class="icon">⚠️</span> Exposure flags</a>
|
|
109
110
|
<a href="#hub-ui" class="sidebar-link"><span class="icon">🖥️</span> Hub UI</a>
|
|
110
111
|
<a href="#search" class="sidebar-link"><span class="icon">🔎</span> Search & qualifiers</a>
|
|
111
112
|
<a href="#cli" class="sidebar-link"><span class="icon">💻</span> CLI commands</a>
|
|
112
113
|
<a href="#actions" class="sidebar-link"><span class="icon">⚙️</span> Tool actions</a>
|
|
114
|
+
<a href="#usage" class="sidebar-link"><span class="icon">📊</span> Usage history</a>
|
|
113
115
|
<a href="#audit" class="sidebar-link"><span class="icon">📝</span> Audit trail</a>
|
|
114
116
|
<a href="#troubleshooting" class="sidebar-link"><span class="icon">🛠️</span> Troubleshooting</a>
|
|
115
117
|
</div>
|
|
@@ -293,6 +295,48 @@ c3_shell(cmd=<span class="str">'terraform apply'</span>, env_creds=<span class="
|
|
|
293
295
|
|
|
294
296
|
<hr class="divider">
|
|
295
297
|
|
|
298
|
+
<!-- ═══════════════════════════════════ STRUCTURED ═══ -->
|
|
299
|
+
<section id="structured" class="tool-section">
|
|
300
|
+
<h2>Structured kinds — cards, addresses, identity (v2.87.0)</h2>
|
|
301
|
+
|
|
302
|
+
<p>Three entry types hold <strong>named fields</strong> instead of one opaque value:
|
|
303
|
+
<code>card</code> (cardholder, number, expiry, optional cvc/billing_zip — Luhn-checked),
|
|
304
|
+
<code>address</code> (street1, city, state, zip, optional recipient/street2/country/phone) and
|
|
305
|
+
<code>identity</code> (full_name, optional dob/ssn/phone/email). The payload is stored as one
|
|
306
|
+
canonical JSON object through the same keyring / encrypted-sidecar path as any other value.</p>
|
|
307
|
+
|
|
308
|
+
<p>They are <strong>inject-only by construction</strong>, which is stricter than a normal secret:</p>
|
|
309
|
+
<ul>
|
|
310
|
+
<li><strong>Reveal is permanently disabled</strong> — <code>agent_readable</code> and
|
|
311
|
+
<code>inject</code> are refused at every surface, for every caller, forever. There is no flag to flip.</li>
|
|
312
|
+
<li><strong>Only single fields cross the boundary.</strong> The agent addresses a field —
|
|
313
|
+
<code>env_creds='CARD.number'</code> (exported as <code>$CARD_NUMBER</code>) or
|
|
314
|
+
<code>{{cred:CARD.number}}</code> inline — and a bare <code>{{cred:CARD}}</code> fails with
|
|
315
|
+
the field list rather than expanding the whole payload.</li>
|
|
316
|
+
<li><strong>The registry shows a projection, not the data.</strong> Lists and the UI display
|
|
317
|
+
<code>visa ••••4242</code> for a card (brand + last4, deliberately <em>not</em> expiry),
|
|
318
|
+
city/state for an address, the name for an identity. Field <em>names</em> are public;
|
|
319
|
+
field <em>values</em> never transit any HTTP response — a sweep test enforces this.</li>
|
|
320
|
+
<li><strong>Echoes redact per field</strong> to <code>[cred:NAME.field]</code>. Caveat: the
|
|
321
|
+
redactor only tracks values of 4+ characters, so a 3-digit CVC or 2-letter state that a
|
|
322
|
+
child process echoes cannot be scrubbed after the fact. The real guarantee remains
|
|
323
|
+
decode-at-the-subprocess-boundary; redaction is the belt over it.</li>
|
|
324
|
+
<li><strong>The type boundary is immutable.</strong> A card cannot be rewritten into a
|
|
325
|
+
plain token (or vice versa) by <code>set</code>, metadata update, or <code>.env</code>
|
|
326
|
+
import — delete and re-create is the only path across, and a keyring attestation keeps an
|
|
327
|
+
entry structured even if <code>.c3/config.json</code> is edited by hand.</li>
|
|
328
|
+
</ul>
|
|
329
|
+
|
|
330
|
+
<p>Updating one field never requires retyping the rest: a partial payload
|
|
331
|
+
<strong>merges</strong> (<code>{"expiry": "01/30"}</code> updates the expiry, JSON
|
|
332
|
+
<code>null</code> deletes an optional field). Read-back for <em>you</em> is terminal-only:
|
|
333
|
+
<code>c3 creds get NAME --show</code> (all fields) or <code>--show --field number</code> —
|
|
334
|
+
the browser and the mobile gateway never carry the values, and mobile cannot create
|
|
335
|
+
structured entries at all.</p>
|
|
336
|
+
</section>
|
|
337
|
+
|
|
338
|
+
<hr class="divider">
|
|
339
|
+
|
|
296
340
|
<!-- ═══════════════════════════════════════ EXPOSURE ═══ -->
|
|
297
341
|
<section id="exposure" class="tool-section">
|
|
298
342
|
<h2>Exposure flags</h2>
|
|
@@ -478,6 +522,42 @@ c3_shell(cmd=<span class="str">'terraform apply'</span>, env_creds=<span class="
|
|
|
478
522
|
<hr class="divider">
|
|
479
523
|
|
|
480
524
|
<!-- ═══════════════════════════════════════ AUDIT ═══ -->
|
|
525
|
+
<section id="usage" class="tool-section">
|
|
526
|
+
<h2>Usage history (v2.88.0)</h2>
|
|
527
|
+
|
|
528
|
+
<p>Every time a value leaves the vault — an <code>env_creds</code> injection, a
|
|
529
|
+
<code>{{cred:NAME}}</code> expansion, a gated reveal, a terminal
|
|
530
|
+
<code>c3 creds get --show</code> — one event is appended to the owning scope's
|
|
531
|
+
<code>.c3/cred_usage.jsonl</code>: timestamp, name (and field for structured entries),
|
|
532
|
+
action, surface, project, exit code, and the command in its <strong>raw template
|
|
533
|
+
form</strong>, capped at 120 characters. Never the expanded string, never a value.
|
|
534
|
+
A global credential's usage from every project lands in <code>~/.c3</code>, so its
|
|
535
|
+
history is complete in one place.</p>
|
|
536
|
+
|
|
537
|
+
<p>Reading it back:</p>
|
|
538
|
+
<ul>
|
|
539
|
+
<li><strong>UI</strong> — the Credentials tab's <em>usage</em> sub-view (totals,
|
|
540
|
+
per-credential counts by surface, expandable recent events) and the hub drawer's
|
|
541
|
+
“Usage & relationships” section.</li>
|
|
542
|
+
<li><strong>CLI</strong> — <code>c3 creds usage [NAME] [--limit N] [--json]</code>.</li>
|
|
543
|
+
<li><strong>Agent</strong> — <code>c3_credentials(action='usage')</code>. Scoped on
|
|
544
|
+
purpose: the agent sees full events (including command previews) only for the
|
|
545
|
+
<em>current</em> project; other projects' use of a shared global credential is
|
|
546
|
+
reduced to counts, so one project's agent cannot read another's command lines
|
|
547
|
+
through the vault. Your surfaces (UI/CLI) show everything.</li>
|
|
548
|
+
<li><strong>REST</strong> — <code>GET /api/credentials/usage</code> and
|
|
549
|
+
<code>GET /api/credentials/<name>/usage</code> (hub:
|
|
550
|
+
<code>/api/projects/credentials/usage</code>).</li>
|
|
551
|
+
</ul>
|
|
552
|
+
|
|
553
|
+
<p>The log rotates at 512KB (one <code>.1</code> generation retained), both filenames
|
|
554
|
+
are vault-write-protected and gitignored, and the lightweight
|
|
555
|
+
<code>last_used</code>/<code>use_count</code> counters you already see on list rows
|
|
556
|
+
keep working exactly as before — they are the summary; this is the history.</p>
|
|
557
|
+
</section>
|
|
558
|
+
|
|
559
|
+
<hr class="divider">
|
|
560
|
+
|
|
481
561
|
<section id="audit" class="tool-section">
|
|
482
562
|
<h2>Audit trail</h2>
|
|
483
563
|
|
|
@@ -113,7 +113,8 @@ _WRITE_CLASS_ALWAYS = frozenset({"Edit", "Write", "MultiEdit"})
|
|
|
113
113
|
# Vault files no native write may touch, regardless of unlock state.
|
|
114
114
|
# Mirrors services.credential_store.VAULT_PROTECTED_FILES (parity-tested);
|
|
115
115
|
# duplicated because hooks must stay import-light.
|
|
116
|
-
_VAULT_FILES = frozenset({"config.json", "secrets.enc", "cred_state.json"
|
|
116
|
+
_VAULT_FILES = frozenset({"config.json", "secrets.enc", "cred_state.json",
|
|
117
|
+
"cred_usage.jsonl", "cred_usage.jsonl.1"})
|
|
117
118
|
|
|
118
119
|
# Redirect messages per native tool
|
|
119
120
|
_REDIRECTS = {
|
|
@@ -2026,7 +2026,9 @@ def api_projects_credentials_set():
|
|
|
2026
2026
|
str(data.get("path") or "").strip(), scope, mutation=True)
|
|
2027
2027
|
if err:
|
|
2028
2028
|
return err
|
|
2029
|
-
value =
|
|
2029
|
+
value = data.get("value")
|
|
2030
|
+
# Structured kinds submit a field OBJECT; the store takes JSON text.
|
|
2031
|
+
value = json.dumps(value) if isinstance(value, dict) else str(value or "")
|
|
2030
2032
|
ctype = str(data.get("type") or data.get("ctype") or "token")
|
|
2031
2033
|
try:
|
|
2032
2034
|
if value:
|
|
@@ -2123,11 +2125,40 @@ def api_projects_credentials_check(name):
|
|
|
2123
2125
|
"name": name,
|
|
2124
2126
|
"scope": entry["scope"],
|
|
2125
2127
|
"storage": entry.get("storage", "keyring"),
|
|
2126
|
-
|
|
2128
|
+
# is_resolvable, not get_value: a structured entry never resolves
|
|
2129
|
+
# whole, but its payload being decodable is what "check" asks.
|
|
2130
|
+
"resolvable": cred_store.is_resolvable(name, project_path=store_path),
|
|
2127
2131
|
"fingerprint": cred_store.fingerprint(name, project_path=store_path),
|
|
2128
2132
|
})
|
|
2129
2133
|
|
|
2130
2134
|
|
|
2135
|
+
@app.route("/api/projects/credentials/usage", methods=["GET"])
|
|
2136
|
+
def api_projects_credentials_usage():
|
|
2137
|
+
"""Usage history — `path` scopes to a project (merged view); omit it for
|
|
2138
|
+
the global vault only. `name` filters to one credential. Names, counts
|
|
2139
|
+
and cmd previews only; never values."""
|
|
2140
|
+
from services import cred_telemetry as ct
|
|
2141
|
+
from services import credential_store as cred_store
|
|
2142
|
+
path = (request.args.get("path") or "").strip()
|
|
2143
|
+
if path:
|
|
2144
|
+
try:
|
|
2145
|
+
base = str(_resolve_project_path(path))
|
|
2146
|
+
except ValueError as e:
|
|
2147
|
+
return jsonify({"error": str(e)}), 404
|
|
2148
|
+
else:
|
|
2149
|
+
home = cred_store.global_base()
|
|
2150
|
+
if home is None:
|
|
2151
|
+
return jsonify({"error": "global scope unresolvable"}), 500
|
|
2152
|
+
base = str(home)
|
|
2153
|
+
name = (request.args.get("name") or "").strip()
|
|
2154
|
+
return jsonify({
|
|
2155
|
+
"path": base if path else "",
|
|
2156
|
+
"aggregate": ct.aggregate(base, name=name),
|
|
2157
|
+
"recent": ct.search_events(base, name=name,
|
|
2158
|
+
limit=request.args.get("limit", 100)),
|
|
2159
|
+
})
|
|
2160
|
+
|
|
2161
|
+
|
|
2131
2162
|
@app.route("/api/hub/credentials/overview", methods=["GET"])
|
|
2132
2163
|
def api_hub_credentials_overview():
|
|
2133
2164
|
"""Cross-project credential inventory: the global vault plus each
|
{code_context_control-2.86.0 → code_context_control-2.88.2}/cli/hub_ui/components/drill_panel.js
RENAMED
|
@@ -182,8 +182,8 @@ function DrillPanel({ project, tab, setTab, onClose, onChanged, onOpenModal, pro
|
|
|
182
182
|
</button>
|
|
183
183
|
</div>
|
|
184
184
|
<div style={{
|
|
185
|
-
display: 'flex', gap: 2, padding: '4px 20px 0',
|
|
186
|
-
borderBottom: `1px solid ${T.border}`,
|
|
185
|
+
display: 'flex', flexWrap: 'wrap', gap: 2, padding: '4px 20px 0',
|
|
186
|
+
borderBottom: `1px solid ${T.border}`, flexShrink: 0,
|
|
187
187
|
}}>
|
|
188
188
|
{tabs.map(([id, label]) => (
|
|
189
189
|
<button key={id} onClick={() => setTab(id)} style={{
|