footprinter-cli 1.0.3__tar.gz → 1.0.5__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.
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/PKG-INFO +34 -71
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/README.md +31 -70
- footprinter_cli-1.0.3/footprinter/access.py → footprinter_cli-1.0.5/footprinter/access_stamper.py +80 -35
- footprinter_cli-1.0.5/footprinter/api/__main__.py +5 -0
- footprinter_cli-1.0.5/footprinter/api/db.py +38 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/api/entities.py +0 -2
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/api/server.py +44 -2
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/bundled/config.example.yaml +3 -15
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/cli/__init__.py +24 -19
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/cli/_common.py +99 -32
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/cli/_policy_helpers.py +153 -112
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/cli/_prompt.py +1 -1
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/cli/_vectorize_stage.py +11 -4
- footprinter_cli-1.0.5/footprinter/cli/add.py +813 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/cli/connect.py +3 -3
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/cli/delete.py +4 -4
- footprinter_cli-1.0.5/footprinter/cli/diagnostics.py +148 -0
- footprinter_cli-1.0.5/footprinter/cli/doctor.py +410 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/cli/ingest.py +21 -324
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/cli/mcp_setup.py +11 -107
- footprinter_cli-1.0.5/footprinter/cli/permission_cmd.py +577 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/cli/search.py +61 -3
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/cli/setup.py +78 -421
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/cli/status.py +118 -3
- footprinter_cli-1.0.5/footprinter/cli/update.py +884 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/cli/view.py +221 -7
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/connectors/__init__.py +2 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/db/__init__.py +8 -1
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/db/browser.py +36 -53
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/db/chats.py +52 -67
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/db/clients.py +35 -26
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/db/emails.py +18 -49
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/db/files.py +52 -105
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/db/folders.py +85 -62
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/db/messages.py +18 -9
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/db/policies.py +3 -3
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/db/projects.py +74 -129
- footprinter_cli-1.0.5/footprinter/db/protocols.py +16 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/db/search.py +50 -32
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/db/sql_utils.py +64 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/db/status.py +39 -9
- footprinter_cli-1.0.3/footprinter/mcp/db.py → footprinter_cli-1.0.5/footprinter/db_base.py +10 -25
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/adapters/browser.py +4 -4
- footprinter_cli-1.0.5/footprinter/ingest/adapters/chat.py +120 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/adapters/local_files.py +1 -1
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/adapters/local_folders.py +6 -6
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/adapters/protocol.py +1 -1
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/browser_indexer.py +1 -1
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/chat_indexer.py +2 -4
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/chat_parsers/__init__.py +2 -1
- footprinter_cli-1.0.5/footprinter/ingest/chat_parsers/claude_code_parser.py +165 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/db/schema.py +216 -114
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/file_indexer.py +23 -15
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/file_scanner.py +16 -6
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/folder_indexer.py +3 -3
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/full_content_extractor.py +24 -39
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/orchestrator.py +8 -10
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/pipe_runner.py +0 -7
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/processing.py +31 -10
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/registry.py +2 -2
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/scan_summary.py +1 -1
- footprinter_cli-1.0.5/footprinter/ingest/status.py +133 -0
- footprinter_cli-1.0.3/footprinter/ingest/cli.py → footprinter_cli-1.0.5/footprinter/ingest/vector_ops.py +17 -18
- footprinter_cli-1.0.5/footprinter/mcp/db.py +34 -0
- footprinter_cli-1.0.5/footprinter/mcp/resources/__init__.py +1 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/mcp/resources/discoverability.py +1 -1
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/mcp/tools/navigation.py +3 -18
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/mcp/tools/read.py +1 -1
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/mcp/tools/search.py +1 -9
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/permissions.py +3 -3
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/semantic/chunking.py +27 -4
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/semantic/embeddings.py +1 -1
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/semantic/hybrid_search.py +3 -8
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/semantic/vector_store.py +26 -9
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/__init__.py +7 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/access_service.py +33 -19
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/chat_service.py +4 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/client_service.py +4 -9
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/content_service.py +15 -5
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/ingest_service.py +4 -6
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/project_service.py +14 -32
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/search_service.py +7 -41
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/semantic_service.py +10 -10
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/visit_service.py +5 -1
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/source_registry.py +1 -1
- footprinter_cli-1.0.5/footprinter/utils/exceptions.py +5 -0
- footprinter_cli-1.0.5/footprinter/utils/paths.py +15 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/visibility.py +83 -45
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter_cli.egg-info/PKG-INFO +34 -71
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter_cli.egg-info/SOURCES.txt +16 -12
- footprinter_cli-1.0.5/footprinter_cli.egg-info/entry_points.txt +4 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/pyproject.toml +5 -1
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_access_control_bypasses.py +13 -13
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_access_control_docs.py +2 -2
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_access_recalculate.py +441 -162
- footprinter_cli-1.0.5/tests/test_access_source_provenance.py +263 -0
- footprinter_cli-1.0.5/tests/test_db_base.py +96 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_e2e_install.py +48 -65
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_edit_recalculate.py +18 -18
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_files_surface.py +3 -3
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_inherit_resolution.py +13 -13
- footprinter_cli-1.0.5/tests/test_no_issue_ids.py +53 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_pip_install_e2e.py +4 -6
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_resolver.py +17 -10
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_security_layer.py +87 -88
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_security_permissions.py +26 -26
- footprinter_cli-1.0.3/footprinter/api/db.py +0 -61
- footprinter_cli-1.0.3/footprinter/cli/api_cmd.py +0 -61
- footprinter_cli-1.0.3/footprinter/cli/data.py +0 -879
- footprinter_cli-1.0.3/footprinter/cli/doctor.py +0 -251
- footprinter_cli-1.0.3/footprinter/cli/mcp_cmd.py +0 -750
- footprinter_cli-1.0.3/footprinter/cli/search_cmd.py +0 -69
- footprinter_cli-1.0.3/footprinter/cli/status_cmd.py +0 -104
- footprinter_cli-1.0.3/footprinter/cli/upsert.py +0 -792
- footprinter_cli-1.0.3/footprinter/cli/vectorize_cmd.py +0 -215
- footprinter_cli-1.0.3/footprinter/ingest/adapters/chat.py +0 -57
- footprinter_cli-1.0.3/footprinter/ingest/db/migration.py +0 -371
- footprinter_cli-1.0.3/footprinter/ingest/db/security.py +0 -6
- footprinter_cli-1.0.3/footprinter/ingest/status.py +0 -347
- footprinter_cli-1.0.3/footprinter/mcp/resources/__init__.py +0 -1
- footprinter_cli-1.0.3/footprinter_cli.egg-info/entry_points.txt +0 -2
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/LICENSE +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/__init__.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/api/__init__.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/api/search.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/api/semantic.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/api/status.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/bundled/__init__.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/bundled/patterns/context_patterns.yaml +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/bundled/patterns/extensions.yaml +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/bundled/patterns/filename_patterns.yaml +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/bundled/patterns/mime_mappings.yaml +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/bundled/patterns/salesforce_rules.yaml +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/bundled/patterns/security_patterns.yaml +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/cli/__main__.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/cli/uninstall.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/connectors/config_utils.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/db/uploads.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/__init__.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/adapters/__init__.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/adapters/ingest.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/chat_parsers/chatgpt_parser.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/chat_parsers/claude_parser.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/content_extractors.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/database.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/db/__init__.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/db/connector_schema.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/ingest/run_record.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/mcp/__init__.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/mcp/__main__.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/mcp/errors.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/mcp/resources/context.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/mcp/server.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/mcp/tools/__init__.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/mcp/tools/semantic.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/mcp/tools/status.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/paths.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/semantic/__init__.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/email_service.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/file_service.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/folder_service.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/includes.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/roles.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/services/status_service.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/utils/__init__.py +0 -0
- {footprinter_cli-1.0.3/footprinter/mcp → footprinter_cli-1.0.5/footprinter/utils}/extraction.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/utils/hash_utils.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/utils/logging_config.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/utils/mime.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/utils/text.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter/utils/time.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter_cli.egg-info/dependency_links.txt +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter_cli.egg-info/requires.txt +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/footprinter_cli.egg-info/top_level.txt +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/setup.cfg +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_build_status_filter.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_bundled.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_e2e_pipeline.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_examples.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_files_rename.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_logging.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_no_project_root.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_package_init.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_paths_no_test_marker.py +0 -0
- {footprinter_cli-1.0.3 → footprinter_cli-1.0.5}/tests/test_prompt_safety.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: footprinter-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.5
|
|
4
4
|
Summary: A local context layer for your files, browser history, chats, and email — searchable, user-owned, MCP-served.
|
|
5
5
|
Author: SwellCity Group
|
|
6
6
|
License: MIT
|
|
@@ -20,6 +20,8 @@ Classifier: Operating System :: MacOS
|
|
|
20
20
|
Classifier: Operating System :: POSIX :: Linux
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.11
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
25
|
Classifier: Topic :: Database
|
|
24
26
|
Classifier: Topic :: Text Processing :: Indexing
|
|
25
27
|
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
@@ -59,67 +61,52 @@ Requires-Dist: httpx<1.0,>=0.27.0; extra == "dev"
|
|
|
59
61
|
|
|
60
62
|
Your work lives across filesystems, browsers, inboxes, chat histories, and other tools. Footprinter indexes those sources into a single local store, organizes them into the projects and groupings you define, and serves the result to AI agents through a governed access layer. You control what the agent can see. Everything stays on your machine.
|
|
61
63
|
|
|
62
|
-
## Prerequisites
|
|
63
|
-
|
|
64
|
-
- **Python 3.11 or newer.** Stock macOS ships with Python 3.9, which won't work — install a newer Python from [python.org](https://www.python.org/downloads/) (recommended) or via `brew install python@3.11`.
|
|
65
|
-
- **macOS 13+** or **Linux**.
|
|
66
|
-
- **Full Disk Access on macOS** for browser history indexing. Grant it to your terminal app under *System Settings → Privacy & Security → Full Disk Access*. `fp setup` will guide you through this when needed.
|
|
67
|
-
|
|
68
64
|
## Install
|
|
69
65
|
|
|
70
|
-
|
|
66
|
+
Requires **Python 3.11+** and **macOS 13+** or **Linux**. The install script checks your Python version and handles the rest:
|
|
71
67
|
|
|
72
68
|
```bash
|
|
73
|
-
# Base install (CLI + MCP + HTTP API)
|
|
74
69
|
curl -fsSL https://raw.githubusercontent.com/harringjohn/footprinter-cli/main/scripts/release/install.sh | bash
|
|
75
|
-
|
|
76
|
-
# Full install (adds semantic search + document parsing)
|
|
77
|
-
curl -fsSL https://raw.githubusercontent.com/harringjohn/footprinter-cli/main/scripts/release/install-full.sh | bash
|
|
78
70
|
```
|
|
79
71
|
|
|
80
|
-
|
|
72
|
+
Or install with **pipx** directly:
|
|
81
73
|
|
|
82
74
|
```bash
|
|
83
|
-
brew install pipx
|
|
84
|
-
pipx ensurepath # then restart your terminal
|
|
85
75
|
pipx install footprinter-cli
|
|
86
|
-
pipx install 'footprinter-cli[full]' # with semantic + parse
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
> **macOS caveats for manual installs:**
|
|
90
|
-
> - **zsh** treats `[...]` as a glob, so keep the single quotes around any bracketed extras specifier (e.g. `'footprinter-cli[full]'`). Without quotes you'll see `zsh: no matches found`.
|
|
91
|
-
> - **System and Homebrew Python** ship with PEP 668 enabled, which blocks bare `pip install` outside a venv. Use pipx (above) instead.
|
|
92
|
-
> - **python.org-distributed Python** doesn't enforce PEP 668, so a bare `pip install footprinter-cli` outside pipx or a venv may succeed but place `fp` in `/Library/Frameworks/Python.framework/Versions/<x.y>/bin`, which isn't on `PATH` by default. Use pipx (above) or the install script.
|
|
93
|
-
|
|
94
|
-
Inside an existing venv, `pip` works as expected:
|
|
95
|
-
|
|
96
|
-
```bash
|
|
97
|
-
./venv/bin/pip install footprinter-cli
|
|
98
|
-
./venv/bin/pip install 'footprinter-cli[full]'
|
|
99
76
|
```
|
|
100
77
|
|
|
101
|
-
|
|
78
|
+
Either method installs three commands: `fp` (the CLI and indexing pipeline), `fp-mcp` (the MCP server for AI agents), and `fp-api` (the HTTP API). Optional extras add more:
|
|
102
79
|
|
|
103
80
|
| Extra | What it adds |
|
|
104
81
|
|-------|-------------|
|
|
105
82
|
| `[semantic]` | Semantic search via ChromaDB + ONNX embeddings |
|
|
106
83
|
| `[parse]` | PDF, Word, Excel, PowerPoint content extraction |
|
|
107
|
-
| `[full]` |
|
|
84
|
+
| `[full]` | Both of the above |
|
|
108
85
|
|
|
109
|
-
|
|
110
|
-
> the ChromaDB client with `anonymized_telemetry=False`, so no telemetry is sent
|
|
111
|
-
> regardless of which version pip resolves. ChromaDB also removed product telemetry
|
|
112
|
-
> entirely in version 1.5.4. See
|
|
113
|
-
> [Chroma OSS overview](https://docs.trychroma.com/docs/overview/oss) for details.
|
|
86
|
+
To install with extras: use the [full install script](https://raw.githubusercontent.com/harringjohn/footprinter-cli/main/scripts/release/install-full.sh), or `pipx install 'footprinter-cli[full]'`.
|
|
114
87
|
|
|
115
|
-
|
|
88
|
+
<details>
|
|
89
|
+
<summary>Troubleshooting & alternative install methods</summary>
|
|
90
|
+
|
|
91
|
+
**Python version:** Stock macOS ships Python 3.9. Install 3.11+ from [python.org](https://www.python.org/downloads/) or `brew install python@3.11`.
|
|
92
|
+
|
|
93
|
+
**macOS caveats:**
|
|
94
|
+
- zsh treats `[...]` as a glob — quote extras specifiers: `'footprinter-cli[full]'`
|
|
95
|
+
- System/Homebrew Python blocks bare `pip install` (PEP 668) — use pipx or a venv instead
|
|
96
|
+
|
|
97
|
+
**Inside an existing venv:** `pip install footprinter-cli` works as expected.
|
|
98
|
+
|
|
99
|
+
**Full Disk Access:** Required for browser history indexing on macOS. `fp setup` will prompt you when needed.
|
|
100
|
+
|
|
101
|
+
**ChromaDB telemetry:** Footprinter sets `anonymized_telemetry=False`. ChromaDB also removed product telemetry in v1.5.4. See [Chroma OSS overview](https://docs.trychroma.com/docs/overview/oss).
|
|
116
102
|
|
|
117
|
-
|
|
103
|
+
</details>
|
|
104
|
+
|
|
105
|
+
### Uninstall
|
|
118
106
|
|
|
119
107
|
```bash
|
|
120
|
-
fp uninstall
|
|
121
|
-
pipx uninstall footprinter-cli
|
|
122
|
-
./venv/bin/pip uninstall footprinter-cli # if you installed inside a venv
|
|
108
|
+
fp uninstall # remove MCP entry + user data
|
|
109
|
+
pipx uninstall footprinter-cli # remove the package
|
|
123
110
|
```
|
|
124
111
|
|
|
125
112
|
## Quick Start
|
|
@@ -156,14 +143,12 @@ Once configured, Claude can search your files, browse projects, and find related
|
|
|
156
143
|
| **Local files** | Path, type, size, timestamps, content hash |
|
|
157
144
|
| **Browser history** | Safari and Chrome — URLs, titles, visit times |
|
|
158
145
|
| **Chat exports** | Claude and ChatGPT conversation exports |
|
|
159
|
-
| **Email** | Subject, sender, recipients, body, timestamps
|
|
146
|
+
| **Email** | Subject, sender, recipients, body, timestamps |
|
|
160
147
|
| **Documents** | PDF, Word, Excel, PowerPoint content (with `[parse]` extra) |
|
|
161
148
|
| **Semantic embeddings** | Conceptual similarity across all sources (with `[semantic]` extra) |
|
|
162
149
|
|
|
163
150
|
What lands in the database — and when — is controlled by the **content storage tier** you opt into. By default, Footprinter only indexes metadata; it does not read your file content until you explicitly enable it. See [Content Storage](https://github.com/harringjohn/footprinter-cli/blob/main/reference/content-storage.md) for the full breakdown.
|
|
164
151
|
|
|
165
|
-
Additional sources are available through [connector plugins](#connectors).
|
|
166
|
-
|
|
167
152
|
## CLI Commands
|
|
168
153
|
|
|
169
154
|
All commands use the `fp` entry point.
|
|
@@ -175,41 +160,21 @@ All commands use the `fp` entry point.
|
|
|
175
160
|
| `fp status` | System health and data counts |
|
|
176
161
|
| `fp search` | Search across all indexed sources |
|
|
177
162
|
| `fp connect` | Manage optional integrations |
|
|
178
|
-
| `fp
|
|
179
|
-
| `fp api` | Start the HTTP API server |
|
|
163
|
+
| `fp permission` | Manage access policies (visibility, permissions) |
|
|
180
164
|
| `fp view` | Browse indexed data (files, folders, projects, clients, chats, emails, visits) |
|
|
181
|
-
| `fp
|
|
182
|
-
| `fp
|
|
165
|
+
| `fp add` | Create new entity records or import from CSV |
|
|
166
|
+
| `fp update` | Update existing records by ID — status, assignments, metadata |
|
|
183
167
|
| `fp delete` | Hard-delete a super entity (irreversible) |
|
|
184
|
-
| `fp
|
|
185
|
-
| `fp doctor` | Post-install health check (Python version, install location, FDA, MCP wiring) |
|
|
168
|
+
| `fp doctor` | Post-install health check (Python version, platform, FDA, MCP wiring) |
|
|
186
169
|
| `fp uninstall` | Remove Footprinter — MCP entry, user data, package |
|
|
187
170
|
|
|
188
171
|
Run `fp <command> --help` for full usage.
|
|
189
172
|
|
|
190
|
-
## Connectors
|
|
191
|
-
|
|
192
|
-
Connector plugins add external data sources like email, cloud storage, and third-party services. They install alongside Footprinter and register automatically:
|
|
193
|
-
|
|
194
|
-
```bash
|
|
195
|
-
pip install footprinter-<name>
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
First-party and community connectors are in development — check the repository for updates.
|
|
199
|
-
|
|
200
|
-
Use `fp connect list` to see available connectors and their status.
|
|
201
|
-
|
|
202
173
|
## Architecture
|
|
203
174
|
|
|
204
175
|
Single-process CLI with optional MCP server. SQLite database. No containers, no cloud, no accounts.
|
|
205
176
|
|
|
206
|
-
Sources are scanned into SQLite with bidirectional links connecting local files to remote backups via content hash matching. Embeddings are generated at ingest time for semantic search. The MCP server exposes indexed data with two-layer access control (visibility +
|
|
207
|
-
|
|
208
|
-
## Requirements
|
|
209
|
-
|
|
210
|
-
- Python 3.11+
|
|
211
|
-
- macOS 13+ or Linux
|
|
212
|
-
- Full Disk Access on macOS (for browser history)
|
|
177
|
+
Sources are scanned into SQLite with bidirectional links connecting local files to remote backups via content hash matching. Embeddings are generated at ingest time for semantic search. The MCP server exposes indexed data with two-layer access control (visibility + access) — you decide what agents can see.
|
|
213
178
|
|
|
214
179
|
## Documentation
|
|
215
180
|
|
|
@@ -223,13 +188,11 @@ Sources are scanned into SQLite with bidirectional links connecting local files
|
|
|
223
188
|
|
|
224
189
|
Bug fixes, documentation, and tests welcome. For new features or architectural changes, [open an issue](https://github.com/harringjohn/footprinter-cli/issues) first to discuss the approach.
|
|
225
190
|
|
|
226
|
-
Connector plugins use an internal API that isn't stable yet — we're not accepting connector contributions at this time.
|
|
227
|
-
|
|
228
191
|
### Development setup
|
|
229
192
|
|
|
230
193
|
```bash
|
|
231
194
|
git clone https://github.com/harringjohn/footprinter-cli.git
|
|
232
|
-
cd footprinter
|
|
195
|
+
cd footprinter-cli
|
|
233
196
|
python3 -m venv venv
|
|
234
197
|
./venv/bin/pip install -e ".[dev]"
|
|
235
198
|
```
|
|
@@ -7,67 +7,52 @@
|
|
|
7
7
|
|
|
8
8
|
Your work lives across filesystems, browsers, inboxes, chat histories, and other tools. Footprinter indexes those sources into a single local store, organizes them into the projects and groupings you define, and serves the result to AI agents through a governed access layer. You control what the agent can see. Everything stays on your machine.
|
|
9
9
|
|
|
10
|
-
## Prerequisites
|
|
11
|
-
|
|
12
|
-
- **Python 3.11 or newer.** Stock macOS ships with Python 3.9, which won't work — install a newer Python from [python.org](https://www.python.org/downloads/) (recommended) or via `brew install python@3.11`.
|
|
13
|
-
- **macOS 13+** or **Linux**.
|
|
14
|
-
- **Full Disk Access on macOS** for browser history indexing. Grant it to your terminal app under *System Settings → Privacy & Security → Full Disk Access*. `fp setup` will guide you through this when needed.
|
|
15
|
-
|
|
16
10
|
## Install
|
|
17
11
|
|
|
18
|
-
|
|
12
|
+
Requires **Python 3.11+** and **macOS 13+** or **Linux**. The install script checks your Python version and handles the rest:
|
|
19
13
|
|
|
20
14
|
```bash
|
|
21
|
-
# Base install (CLI + MCP + HTTP API)
|
|
22
15
|
curl -fsSL https://raw.githubusercontent.com/harringjohn/footprinter-cli/main/scripts/release/install.sh | bash
|
|
23
|
-
|
|
24
|
-
# Full install (adds semantic search + document parsing)
|
|
25
|
-
curl -fsSL https://raw.githubusercontent.com/harringjohn/footprinter-cli/main/scripts/release/install-full.sh | bash
|
|
26
16
|
```
|
|
27
17
|
|
|
28
|
-
|
|
18
|
+
Or install with **pipx** directly:
|
|
29
19
|
|
|
30
20
|
```bash
|
|
31
|
-
brew install pipx
|
|
32
|
-
pipx ensurepath # then restart your terminal
|
|
33
21
|
pipx install footprinter-cli
|
|
34
|
-
pipx install 'footprinter-cli[full]' # with semantic + parse
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
> **macOS caveats for manual installs:**
|
|
38
|
-
> - **zsh** treats `[...]` as a glob, so keep the single quotes around any bracketed extras specifier (e.g. `'footprinter-cli[full]'`). Without quotes you'll see `zsh: no matches found`.
|
|
39
|
-
> - **System and Homebrew Python** ship with PEP 668 enabled, which blocks bare `pip install` outside a venv. Use pipx (above) instead.
|
|
40
|
-
> - **python.org-distributed Python** doesn't enforce PEP 668, so a bare `pip install footprinter-cli` outside pipx or a venv may succeed but place `fp` in `/Library/Frameworks/Python.framework/Versions/<x.y>/bin`, which isn't on `PATH` by default. Use pipx (above) or the install script.
|
|
41
|
-
|
|
42
|
-
Inside an existing venv, `pip` works as expected:
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
./venv/bin/pip install footprinter-cli
|
|
46
|
-
./venv/bin/pip install 'footprinter-cli[full]'
|
|
47
22
|
```
|
|
48
23
|
|
|
49
|
-
|
|
24
|
+
Either method installs three commands: `fp` (the CLI and indexing pipeline), `fp-mcp` (the MCP server for AI agents), and `fp-api` (the HTTP API). Optional extras add more:
|
|
50
25
|
|
|
51
26
|
| Extra | What it adds |
|
|
52
27
|
|-------|-------------|
|
|
53
28
|
| `[semantic]` | Semantic search via ChromaDB + ONNX embeddings |
|
|
54
29
|
| `[parse]` | PDF, Word, Excel, PowerPoint content extraction |
|
|
55
|
-
| `[full]` |
|
|
30
|
+
| `[full]` | Both of the above |
|
|
56
31
|
|
|
57
|
-
|
|
58
|
-
> the ChromaDB client with `anonymized_telemetry=False`, so no telemetry is sent
|
|
59
|
-
> regardless of which version pip resolves. ChromaDB also removed product telemetry
|
|
60
|
-
> entirely in version 1.5.4. See
|
|
61
|
-
> [Chroma OSS overview](https://docs.trychroma.com/docs/overview/oss) for details.
|
|
32
|
+
To install with extras: use the [full install script](https://raw.githubusercontent.com/harringjohn/footprinter-cli/main/scripts/release/install-full.sh), or `pipx install 'footprinter-cli[full]'`.
|
|
62
33
|
|
|
63
|
-
|
|
34
|
+
<details>
|
|
35
|
+
<summary>Troubleshooting & alternative install methods</summary>
|
|
36
|
+
|
|
37
|
+
**Python version:** Stock macOS ships Python 3.9. Install 3.11+ from [python.org](https://www.python.org/downloads/) or `brew install python@3.11`.
|
|
38
|
+
|
|
39
|
+
**macOS caveats:**
|
|
40
|
+
- zsh treats `[...]` as a glob — quote extras specifiers: `'footprinter-cli[full]'`
|
|
41
|
+
- System/Homebrew Python blocks bare `pip install` (PEP 668) — use pipx or a venv instead
|
|
42
|
+
|
|
43
|
+
**Inside an existing venv:** `pip install footprinter-cli` works as expected.
|
|
44
|
+
|
|
45
|
+
**Full Disk Access:** Required for browser history indexing on macOS. `fp setup` will prompt you when needed.
|
|
46
|
+
|
|
47
|
+
**ChromaDB telemetry:** Footprinter sets `anonymized_telemetry=False`. ChromaDB also removed product telemetry in v1.5.4. See [Chroma OSS overview](https://docs.trychroma.com/docs/overview/oss).
|
|
64
48
|
|
|
65
|
-
|
|
49
|
+
</details>
|
|
50
|
+
|
|
51
|
+
### Uninstall
|
|
66
52
|
|
|
67
53
|
```bash
|
|
68
|
-
fp uninstall
|
|
69
|
-
pipx uninstall footprinter-cli
|
|
70
|
-
./venv/bin/pip uninstall footprinter-cli # if you installed inside a venv
|
|
54
|
+
fp uninstall # remove MCP entry + user data
|
|
55
|
+
pipx uninstall footprinter-cli # remove the package
|
|
71
56
|
```
|
|
72
57
|
|
|
73
58
|
## Quick Start
|
|
@@ -104,14 +89,12 @@ Once configured, Claude can search your files, browse projects, and find related
|
|
|
104
89
|
| **Local files** | Path, type, size, timestamps, content hash |
|
|
105
90
|
| **Browser history** | Safari and Chrome — URLs, titles, visit times |
|
|
106
91
|
| **Chat exports** | Claude and ChatGPT conversation exports |
|
|
107
|
-
| **Email** | Subject, sender, recipients, body, timestamps
|
|
92
|
+
| **Email** | Subject, sender, recipients, body, timestamps |
|
|
108
93
|
| **Documents** | PDF, Word, Excel, PowerPoint content (with `[parse]` extra) |
|
|
109
94
|
| **Semantic embeddings** | Conceptual similarity across all sources (with `[semantic]` extra) |
|
|
110
95
|
|
|
111
96
|
What lands in the database — and when — is controlled by the **content storage tier** you opt into. By default, Footprinter only indexes metadata; it does not read your file content until you explicitly enable it. See [Content Storage](https://github.com/harringjohn/footprinter-cli/blob/main/reference/content-storage.md) for the full breakdown.
|
|
112
97
|
|
|
113
|
-
Additional sources are available through [connector plugins](#connectors).
|
|
114
|
-
|
|
115
98
|
## CLI Commands
|
|
116
99
|
|
|
117
100
|
All commands use the `fp` entry point.
|
|
@@ -123,41 +106,21 @@ All commands use the `fp` entry point.
|
|
|
123
106
|
| `fp status` | System health and data counts |
|
|
124
107
|
| `fp search` | Search across all indexed sources |
|
|
125
108
|
| `fp connect` | Manage optional integrations |
|
|
126
|
-
| `fp
|
|
127
|
-
| `fp api` | Start the HTTP API server |
|
|
109
|
+
| `fp permission` | Manage access policies (visibility, permissions) |
|
|
128
110
|
| `fp view` | Browse indexed data (files, folders, projects, clients, chats, emails, visits) |
|
|
129
|
-
| `fp
|
|
130
|
-
| `fp
|
|
111
|
+
| `fp add` | Create new entity records or import from CSV |
|
|
112
|
+
| `fp update` | Update existing records by ID — status, assignments, metadata |
|
|
131
113
|
| `fp delete` | Hard-delete a super entity (irreversible) |
|
|
132
|
-
| `fp
|
|
133
|
-
| `fp doctor` | Post-install health check (Python version, install location, FDA, MCP wiring) |
|
|
114
|
+
| `fp doctor` | Post-install health check (Python version, platform, FDA, MCP wiring) |
|
|
134
115
|
| `fp uninstall` | Remove Footprinter — MCP entry, user data, package |
|
|
135
116
|
|
|
136
117
|
Run `fp <command> --help` for full usage.
|
|
137
118
|
|
|
138
|
-
## Connectors
|
|
139
|
-
|
|
140
|
-
Connector plugins add external data sources like email, cloud storage, and third-party services. They install alongside Footprinter and register automatically:
|
|
141
|
-
|
|
142
|
-
```bash
|
|
143
|
-
pip install footprinter-<name>
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
First-party and community connectors are in development — check the repository for updates.
|
|
147
|
-
|
|
148
|
-
Use `fp connect list` to see available connectors and their status.
|
|
149
|
-
|
|
150
119
|
## Architecture
|
|
151
120
|
|
|
152
121
|
Single-process CLI with optional MCP server. SQLite database. No containers, no cloud, no accounts.
|
|
153
122
|
|
|
154
|
-
Sources are scanned into SQLite with bidirectional links connecting local files to remote backups via content hash matching. Embeddings are generated at ingest time for semantic search. The MCP server exposes indexed data with two-layer access control (visibility +
|
|
155
|
-
|
|
156
|
-
## Requirements
|
|
157
|
-
|
|
158
|
-
- Python 3.11+
|
|
159
|
-
- macOS 13+ or Linux
|
|
160
|
-
- Full Disk Access on macOS (for browser history)
|
|
123
|
+
Sources are scanned into SQLite with bidirectional links connecting local files to remote backups via content hash matching. Embeddings are generated at ingest time for semantic search. The MCP server exposes indexed data with two-layer access control (visibility + access) — you decide what agents can see.
|
|
161
124
|
|
|
162
125
|
## Documentation
|
|
163
126
|
|
|
@@ -171,13 +134,11 @@ Sources are scanned into SQLite with bidirectional links connecting local files
|
|
|
171
134
|
|
|
172
135
|
Bug fixes, documentation, and tests welcome. For new features or architectural changes, [open an issue](https://github.com/harringjohn/footprinter-cli/issues) first to discuss the approach.
|
|
173
136
|
|
|
174
|
-
Connector plugins use an internal API that isn't stable yet — we're not accepting connector contributions at this time.
|
|
175
|
-
|
|
176
137
|
### Development setup
|
|
177
138
|
|
|
178
139
|
```bash
|
|
179
140
|
git clone https://github.com/harringjohn/footprinter-cli.git
|
|
180
|
-
cd footprinter
|
|
141
|
+
cd footprinter-cli
|
|
181
142
|
python3 -m venv venv
|
|
182
143
|
./venv/bin/pip install -e ".[dev]"
|
|
183
144
|
```
|
footprinter_cli-1.0.3/footprinter/access.py → footprinter_cli-1.0.5/footprinter/access_stamper.py
RENAMED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Maps a policy scope (e.g. "global", "project:3", "folder:~/Work/") to affected
|
|
4
4
|
entity rows, calls the existing batch resolve functions, and writes resolved
|
|
5
|
-
values back to
|
|
5
|
+
values back to visibility / access columns.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
@@ -12,6 +12,7 @@ import sqlite3
|
|
|
12
12
|
from collections.abc import Callable
|
|
13
13
|
from typing import Any
|
|
14
14
|
|
|
15
|
+
from footprinter.db.policies import is_folder_path_scope
|
|
15
16
|
from footprinter.permissions import batch_resolve_permissions
|
|
16
17
|
from footprinter.visibility import batch_resolve_visibility
|
|
17
18
|
|
|
@@ -44,8 +45,8 @@ def _is_inherit_source(source: str) -> bool:
|
|
|
44
45
|
# ---------------------------------------------------------------------------
|
|
45
46
|
# Each entry describes an entity type's table and capabilities.
|
|
46
47
|
# table: SQL table name
|
|
47
|
-
# has_visibility: has
|
|
48
|
-
# has_permissions: has
|
|
48
|
+
# has_visibility: has visibility column
|
|
49
|
+
# has_permissions: has access column
|
|
49
50
|
# has_status: has status column (filter WHERE status = 'listed')
|
|
50
51
|
# has_project_id: has project_id FK
|
|
51
52
|
# has_client_id: has client_id FK
|
|
@@ -101,7 +102,7 @@ ENTITY_META: dict[str, dict[str, Any]] = {
|
|
|
101
102
|
"has_project_id": False,
|
|
102
103
|
"has_client_id": True,
|
|
103
104
|
"has_account": False,
|
|
104
|
-
"path_column":
|
|
105
|
+
"path_column": None,
|
|
105
106
|
},
|
|
106
107
|
"client": {
|
|
107
108
|
"table": "clients",
|
|
@@ -113,10 +114,21 @@ ENTITY_META: dict[str, dict[str, Any]] = {
|
|
|
113
114
|
"has_account": False,
|
|
114
115
|
"path_column": None,
|
|
115
116
|
},
|
|
117
|
+
"visit": {
|
|
118
|
+
"table": "visits",
|
|
119
|
+
"has_visibility": True,
|
|
120
|
+
"has_permissions": True,
|
|
121
|
+
"has_status": False,
|
|
122
|
+
"has_project_id": False,
|
|
123
|
+
"has_client_id": False,
|
|
124
|
+
"has_account": False,
|
|
125
|
+
"path_column": None,
|
|
126
|
+
},
|
|
116
127
|
}
|
|
117
128
|
|
|
118
129
|
# Reverse map: source scope suffix → entity type (e.g. "files" → "file")
|
|
119
130
|
_SOURCE_TO_ENTITY = {meta["table"]: etype for etype, meta in ENTITY_META.items()}
|
|
131
|
+
_SOURCE_TO_ENTITY["browser"] = "visit"
|
|
120
132
|
|
|
121
133
|
|
|
122
134
|
# ---------------------------------------------------------------------------
|
|
@@ -170,28 +182,58 @@ def _get_ids_for_scope(conn: sqlite3.Connection, scope: str) -> dict[str, list[i
|
|
|
170
182
|
return result
|
|
171
183
|
|
|
172
184
|
if prefix == "folder":
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
185
|
+
if is_folder_path_scope(scope):
|
|
186
|
+
# folder:{path} → files/folders with matching path prefix
|
|
187
|
+
path = os.path.expanduser(value)
|
|
188
|
+
# Escape LIKE metacharacters so literal %, _ in paths match correctly
|
|
189
|
+
escaped = path.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_")
|
|
190
|
+
result = {}
|
|
191
|
+
for etype in ENTITY_META:
|
|
192
|
+
meta = ENTITY_META[etype]
|
|
193
|
+
path_col = meta["path_column"]
|
|
194
|
+
if path_col is None:
|
|
195
|
+
continue
|
|
196
|
+
table = meta["table"]
|
|
197
|
+
where = f"{path_col} LIKE ? ESCAPE '\\'"
|
|
198
|
+
if meta["has_status"]:
|
|
199
|
+
where += " AND status = 'listed'"
|
|
200
|
+
rows = conn.execute(
|
|
201
|
+
f"SELECT id FROM {table} WHERE {where}",
|
|
202
|
+
(escaped + "%",),
|
|
203
|
+
).fetchall()
|
|
204
|
+
ids = [r["id"] for r in rows]
|
|
205
|
+
if ids:
|
|
206
|
+
result[etype] = ids
|
|
207
|
+
return result
|
|
208
|
+
else:
|
|
209
|
+
# folder:{id} → folder + all descendants via parent_folder_id
|
|
210
|
+
folder_id = int(value)
|
|
211
|
+
descendants_cte = """
|
|
212
|
+
WITH RECURSIVE descendants(id) AS (
|
|
213
|
+
SELECT id FROM folders WHERE id = ?
|
|
214
|
+
UNION ALL
|
|
215
|
+
SELECT folder.id FROM folders folder
|
|
216
|
+
JOIN descendants descendant ON folder.parent_folder_id = descendant.id
|
|
217
|
+
)
|
|
218
|
+
"""
|
|
219
|
+
cursor = conn.cursor()
|
|
220
|
+
cursor.execute(
|
|
221
|
+
f"{descendants_cte} SELECT id FROM descendants",
|
|
222
|
+
(folder_id,),
|
|
223
|
+
)
|
|
224
|
+
desc_ids = [row["id"] for row in cursor.fetchall()]
|
|
225
|
+
if not desc_ids:
|
|
226
|
+
return {}
|
|
227
|
+
result: dict[str, list[int]] = {"folder": desc_ids}
|
|
228
|
+
ph = ",".join("?" * len(desc_ids))
|
|
229
|
+
file_rows = conn.execute(
|
|
230
|
+
f"SELECT id FROM files WHERE folder_id IN ({ph}) AND status = 'listed'",
|
|
231
|
+
tuple(desc_ids),
|
|
190
232
|
).fetchall()
|
|
191
|
-
|
|
192
|
-
if
|
|
193
|
-
result[
|
|
194
|
-
|
|
233
|
+
file_ids = [r["id"] for r in file_rows]
|
|
234
|
+
if file_ids:
|
|
235
|
+
result["file"] = file_ids
|
|
236
|
+
return result
|
|
195
237
|
|
|
196
238
|
if prefix == "project":
|
|
197
239
|
project_id = int(value)
|
|
@@ -263,31 +305,34 @@ def _get_ids_for_scope(conn: sqlite3.Connection, scope: str) -> dict[str, list[i
|
|
|
263
305
|
|
|
264
306
|
|
|
265
307
|
def _write_back_visibility(conn: sqlite3.Connection, entity_type: str, results: dict[int, tuple]) -> None:
|
|
266
|
-
"""Batch UPDATE
|
|
308
|
+
"""Batch UPDATE visibility and visibility_source from resolve results.
|
|
267
309
|
|
|
268
310
|
Entities whose visibility comes from the global policy or the hardcoded
|
|
269
|
-
baseline are written as ``'inherit'``
|
|
270
|
-
|
|
311
|
+
baseline are written as ``'inherit'`` with ``visibility_source = NULL``.
|
|
312
|
+
Entities with a specific policy get the resolved value and source scope.
|
|
271
313
|
"""
|
|
272
314
|
table = ENTITY_META[entity_type]["table"]
|
|
273
315
|
conn.executemany(
|
|
274
|
-
f"UPDATE {table} SET
|
|
275
|
-
[
|
|
316
|
+
f"UPDATE {table} SET visibility = ?, visibility_source = ? WHERE id = ?",
|
|
317
|
+
[
|
|
318
|
+
("inherit", None, eid) if _is_inherit_source(source) else (state, source, eid)
|
|
319
|
+
for eid, (state, source) in results.items()
|
|
320
|
+
],
|
|
276
321
|
)
|
|
277
322
|
|
|
278
323
|
|
|
279
324
|
def _write_back_permissions(conn: sqlite3.Connection, entity_type: str, results: dict[int, tuple]) -> None:
|
|
280
|
-
"""Batch UPDATE
|
|
325
|
+
"""Batch UPDATE access and access_source from resolve results.
|
|
281
326
|
|
|
282
327
|
Entities whose permission comes from the global policy or the hardcoded
|
|
283
|
-
baseline are written as ``'inherit'``
|
|
284
|
-
|
|
328
|
+
baseline are written as ``'inherit'`` with ``access_source = NULL``.
|
|
329
|
+
Entities with a specific policy get the resolved value and source scope.
|
|
285
330
|
"""
|
|
286
331
|
table = ENTITY_META[entity_type]["table"]
|
|
287
332
|
conn.executemany(
|
|
288
|
-
f"UPDATE {table} SET
|
|
333
|
+
f"UPDATE {table} SET access = ?, access_source = ? WHERE id = ?",
|
|
289
334
|
[
|
|
290
|
-
("inherit" if _is_inherit_source(source) else ("allow" if allowed else "deny"
|
|
335
|
+
("inherit", None, eid) if _is_inherit_source(source) else ("allow" if allowed else "deny", source, eid)
|
|
291
336
|
for eid, (allowed, source) in results.items()
|
|
292
337
|
],
|
|
293
338
|
)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Database connection for Footprinter HTTP API."""
|
|
2
|
+
|
|
3
|
+
import sqlite3
|
|
4
|
+
from contextlib import contextmanager
|
|
5
|
+
from typing import Generator
|
|
6
|
+
|
|
7
|
+
from footprinter.db_base import open_checked_connection
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@contextmanager
|
|
11
|
+
def get_db() -> Generator[sqlite3.Connection, None, None]:
|
|
12
|
+
"""Context manager for database connections.
|
|
13
|
+
|
|
14
|
+
Divergences from MCP's ``get_db()``:
|
|
15
|
+
|
|
16
|
+
- No ``PRAGMA query_only`` — the HTTP API uses Role.ADMIN and may need
|
|
17
|
+
write access for future endpoints.
|
|
18
|
+
- No ``handle_db_errors`` decorator — ``DatabaseNotInitializedError`` is
|
|
19
|
+
caught by a FastAPI exception handler registered in ``server.create_app()``.
|
|
20
|
+
|
|
21
|
+
Calls ``load_globals()`` to refresh the global visibility/permission
|
|
22
|
+
policy cache in ``access_service`` for the current request.
|
|
23
|
+
"""
|
|
24
|
+
with open_checked_connection() as conn:
|
|
25
|
+
yield conn
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_conn():
|
|
29
|
+
"""FastAPI dependency that yields a database connection.
|
|
30
|
+
|
|
31
|
+
Usage::
|
|
32
|
+
|
|
33
|
+
@router.get("/endpoint")
|
|
34
|
+
def handler(conn=Depends(get_conn)):
|
|
35
|
+
...
|
|
36
|
+
"""
|
|
37
|
+
with get_db() as conn:
|
|
38
|
+
yield conn
|
|
@@ -137,7 +137,6 @@ def list_projects(
|
|
|
137
137
|
include: Optional[str] = Query(None, description="Comma-separated includes"),
|
|
138
138
|
status: Optional[str] = Query(None, description="Comma-separated status filter"),
|
|
139
139
|
client: Optional[str] = None,
|
|
140
|
-
project_type: Optional[str] = None,
|
|
141
140
|
limit: int = Query(50, ge=1, le=MAX_LIMIT),
|
|
142
141
|
page: int = 1,
|
|
143
142
|
):
|
|
@@ -149,7 +148,6 @@ def list_projects(
|
|
|
149
148
|
include=include_list,
|
|
150
149
|
status=status_list,
|
|
151
150
|
client=client,
|
|
152
|
-
project_type=project_type,
|
|
153
151
|
limit=limit,
|
|
154
152
|
page=page,
|
|
155
153
|
)
|