topos-node 1.3.56__tar.gz → 1.4.0__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.
- {topos_node-1.3.56/topos_node.egg-info → topos_node-1.4.0}/PKG-INFO +2 -1
- {topos_node-1.3.56 → topos_node-1.4.0}/pyproject.toml +4 -1
- {topos_node-1.3.56 → topos_node-1.4.0}/shared/filtering.py +44 -16
- topos_node-1.4.0/tests/test_topos_home_hermeticity.py +326 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/__version__.py +2 -2
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/ingestion_api.py +2 -2
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/ingestion_sources.py +3 -3
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/local_mcp.py +30 -11
- topos_node-1.4.0/topos/api/permissions_identity.py +30 -0
- topos_node-1.4.0/topos/api/permissions_ingestion.py +30 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/signal.py +39 -3
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/uma_data.py +71 -137
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/app.py +43 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/auth.py +20 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/canonicalization/declared_field_map.py +50 -2
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/canonicalization/mappers/messenger_mapper.py +2 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/cli/tray.py +195 -53
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/control_plane_client.py +15 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/__init__.py +77 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/database_explorer.py +27 -8
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/ingest.py +8 -3
- topos_node-1.4.0/topos/core/handlers/permissions_v2.py +258 -0
- topos_node-1.4.0/topos/core/handlers/permissions_v2_identity.py +23 -0
- topos_node-1.4.0/topos/core/handlers/permissions_v2_ingestion.py +22 -0
- topos_node-1.4.0/topos/core/handlers/permissions_v2_release.py +16 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/query.py +26 -6
- topos_node-1.4.0/topos/core/handlers/shadow_rescore.py +51 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/signal_features.py +37 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/sources.py +8 -2
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/uma.py +128 -219
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/data_explorer_tables.py +50 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/disclosure/content_policy.py +9 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/derived_tables.py +51 -36
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/job_writer.py +17 -3
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/base.py +14 -0
- topos_node-1.4.0/topos/enrichment/jobs/canonical/entities_job.py +457 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/orchestrator.py +28 -4
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/surfaces.py +26 -1
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/graph_enrichers.py +123 -21
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/maintenance.py +21 -4
- topos_node-1.4.0/topos/features/entities/mention_lineage.py +736 -0
- topos_node-1.4.0/topos/features/entities/mention_lineage_lane.py +382 -0
- topos_node-1.4.0/topos/features/entities/rebuild_subprocess.py +524 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/resolver.py +15 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/structured_fields.py +4 -1
- topos_node-1.4.0/topos/features/facts/evidence_time.py +212 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/facts/extract.py +91 -3
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/facts/llm_extract.py +20 -1
- topos_node-1.4.0/topos/features/facts/reactions.py +43 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/facts/store.py +95 -6
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/facts/verdicts.py +41 -2
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/lifecycle/blackhole.py +32 -10
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/lifecycle/blackhole_guard.py +31 -12
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/lifecycle/blackhole_llm.py +11 -4
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/lifecycle/derived_scrub.py +9 -0
- topos_node-1.4.0/topos/features/lifecycle/record_protection.py +104 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/provenance/roles.py +13 -2
- topos_node-1.4.0/topos/features/temporal/__init__.py +1 -0
- topos_node-1.4.0/topos/features/temporal/points.py +288 -0
- topos_node-1.4.0/topos/features/temporal/records.py +131 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/canonical_pipeline.py +54 -6
- topos_node-1.4.0/topos/ingestion/chatgpt_owner_snapshot.py +409 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/local_sync.py +204 -57
- topos_node-1.4.0/topos/ingestion/owner_snapshot.py +264 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parsers/__init__.py +5 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parsers/messenger_parser.py +2 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/reprocess.py +62 -1
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/sources/imessage_reader.py +112 -41
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/sources/signal_export_parser.py +18 -7
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/sources/signal_reader.py +49 -13
- topos_node-1.4.0/topos/permissions_v2/__init__.py +1 -0
- topos_node-1.4.0/topos/permissions_v2/canonical.py +283 -0
- topos_node-1.4.0/topos/permissions_v2/canonical_floor.py +338 -0
- topos_node-1.4.0/topos/permissions_v2/contract.py +314 -0
- topos_node-1.4.0/topos/permissions_v2/evidence.py +1456 -0
- topos_node-1.4.0/topos/permissions_v2/evidence_review_runtime.py +168 -0
- topos_node-1.4.0/topos/permissions_v2/evidence_reviews.py +218 -0
- topos_node-1.4.0/topos/permissions_v2/exclusion_floor.py +83 -0
- topos_node-1.4.0/topos/permissions_v2/experiments/__init__.py +1 -0
- topos_node-1.4.0/topos/permissions_v2/experiments/__main__.py +27 -0
- topos_node-1.4.0/topos/permissions_v2/experiments/evaluators.py +201 -0
- topos_node-1.4.0/topos/permissions_v2/experiments/fact_bridge.py +675 -0
- topos_node-1.4.0/topos/permissions_v2/experiments/harness.py +147 -0
- topos_node-1.4.0/topos/permissions_v2/experiments/models.py +192 -0
- topos_node-1.4.0/topos/permissions_v2/experiments/retention.py +106 -0
- topos_node-1.4.0/topos/permissions_v2/experiments/scoring.py +212 -0
- topos_node-1.4.0/topos/permissions_v2/experiments/source_bridge.py +556 -0
- topos_node-1.4.0/topos/permissions_v2/experiments/synthetic.py +53 -0
- topos_node-1.4.0/topos/permissions_v2/fact_contract.py +415 -0
- topos_node-1.4.0/topos/permissions_v2/fact_eligibility.py +281 -0
- topos_node-1.4.0/topos/permissions_v2/fact_policy.py +107 -0
- topos_node-1.4.0/topos/permissions_v2/fact_projection.py +247 -0
- topos_node-1.4.0/topos/permissions_v2/fact_release.py +129 -0
- topos_node-1.4.0/topos/permissions_v2/fact_release_transport.py +89 -0
- topos_node-1.4.0/topos/permissions_v2/forwarding.py +83 -0
- topos_node-1.4.0/topos/permissions_v2/identity.py +311 -0
- topos_node-1.4.0/topos/permissions_v2/identity_attestation.py +231 -0
- topos_node-1.4.0/topos/permissions_v2/identity_dispatch.py +68 -0
- topos_node-1.4.0/topos/permissions_v2/identity_protocol.py +207 -0
- topos_node-1.4.0/topos/permissions_v2/ingest_dispatch.py +83 -0
- topos_node-1.4.0/topos/permissions_v2/ingest_protocol.py +256 -0
- topos_node-1.4.0/topos/permissions_v2/ingest_provenance.py +811 -0
- topos_node-1.4.0/topos/permissions_v2/ingest_snapshot_facts.py +135 -0
- topos_node-1.4.0/topos/permissions_v2/ledger.py +538 -0
- topos_node-1.4.0/topos/permissions_v2/ledger_retention.py +29 -0
- topos_node-1.4.0/topos/permissions_v2/node_protocol.py +238 -0
- topos_node-1.4.0/topos/permissions_v2/opaque_ids.py +122 -0
- topos_node-1.4.0/topos/permissions_v2/projection_review_runtime.py +23 -0
- topos_node-1.4.0/topos/permissions_v2/projection_reviews.py +334 -0
- topos_node-1.4.0/topos/permissions_v2/protection_clock.py +753 -0
- topos_node-1.4.0/topos/permissions_v2/protocol.py +247 -0
- topos_node-1.4.0/topos/permissions_v2/registry.py +162 -0
- topos_node-1.4.0/topos/permissions_v2/release.py +352 -0
- topos_node-1.4.0/topos/permissions_v2/release_transport.py +103 -0
- topos_node-1.4.0/topos/permissions_v2/runtime.py +361 -0
- topos_node-1.4.0/topos/permissions_v2/search_contract.py +226 -0
- topos_node-1.4.0/topos/permissions_v2/search_index.py +616 -0
- topos_node-1.4.0/topos/permissions_v2/search_lanes.py +116 -0
- topos_node-1.4.0/topos/permissions_v2/search_release.py +345 -0
- topos_node-1.4.0/topos/permissions_v2/search_transport.py +99 -0
- topos_node-1.4.0/topos/permissions_v2/shadow_index.py +165 -0
- topos_node-1.4.0/topos/permissions_v2/shadow_labeler_local.py +255 -0
- topos_node-1.4.0/topos/permissions_v2/shadow_labelers.py +58 -0
- topos_node-1.4.0/topos/permissions_v2/shadow_rescore.py +225 -0
- topos_node-1.4.0/topos/permissions_v2/signing.py +242 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/pipeline/job_runner.py +110 -1
- topos_node-1.4.0/topos/pipeline/job_secrets.py +124 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/pipeline/job_store.py +82 -5
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/protocol/handled_message_types.json +43 -1
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/aggregate.py +11 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/disclosure.py +28 -7
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/exclusion.py +2 -1
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/inference.py +26 -5
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/manifest.py +13 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/manifest_validation.py +4 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/pipeline.py +56 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/retrieval.py +107 -16
- topos_node-1.4.0/topos/query/truth_door.py +80 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/types.py +3 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/runtime_shutdown.py +60 -2
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sources/install_service.py +15 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sources/scrub_service.py +4 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/adapters/sqlite/stores.py +21 -4
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/canonical/canonical_store.py +285 -16
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/canonical/conversations_tables.py +100 -72
- topos_node-1.4.0/topos/storage/db/migrations/owner_only_records_v1.py +17 -0
- topos_node-1.4.0/topos/storage/db/migrations/permissions_fact_lineage_keys_v1.py +415 -0
- topos_node-1.4.0/topos/storage/db/migrations/permissions_read_path_indexes_v1.py +88 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/registry.py +25 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/registry_checksums.json +1 -0
- topos_node-1.4.0/topos/storage/db/migrations/temporal_fields_v1.py +70 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/write_gate.py +48 -1
- topos_node-1.4.0/topos/uma_authority.py +171 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/uma_filters.py +75 -17
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/upgrades/manifests.json +31 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/upgrades/runner.py +24 -1
- {topos_node-1.3.56 → topos_node-1.4.0/topos_node.egg-info}/PKG-INFO +2 -1
- {topos_node-1.3.56 → topos_node-1.4.0}/topos_node.egg-info/SOURCES.txt +80 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos_node.egg-info/requires.txt +1 -0
- topos_node-1.3.56/topos/enrichment/jobs/canonical/entities_job.py +0 -362
- topos_node-1.3.56/topos/features/entities/rebuild_subprocess.py +0 -260
- {topos_node-1.3.56 → topos_node-1.4.0}/LICENSE +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/MANIFEST.in +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/README.md +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/setup.cfg +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/shared/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/shared/schema_registry.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/tests/test_active_database_binding.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/tests/test_active_ingestion_binding.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/tests/test_extensions.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/tests/test_gate_leg_hermeticity.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/tests/test_llm_integrations_storage.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/tests/test_local_gate_composition.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/tests/test_owner_database_hermeticity.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/tests/test_prewarm_first_run.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/tests/test_profile_hygiene.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/tests/test_profiles.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/tests/test_protocol_handled_types.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/tests/test_query_field_contract.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/tests/test_sync_dep_pins.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/tests/test_system_computer_name.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/analytics/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/analytics/dataset_resolution.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/analytics/duckdb_adapter.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/analytics/luck_surface.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/analytics/messenger_communities.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/analytics/messenger_directed.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/analytics/messenger_graph.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/analytics/messenger_labels.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/analytics/person_graph.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/analytics/person_overlay.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/analytics/profiles.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/analytics/query_engine.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/analytics/raw_queries.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/analytics/relationship_reads.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/analytics.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/app_registry.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/backup.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/community_naming_config.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/compute_remote.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/connected_apps.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/conversation_context.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/data_commit.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/database_explorer.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/db.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/device.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/disk_space_config.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/engine_run.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/enrichment.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/enrichment_lab.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/facts_llm_config.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/filter_lab.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/health.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/home_chat.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/ingestion_compat.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/intelligence_lifecycle.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/llm.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/messenger_analytics.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/privacy_disclose.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/query_api.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/runtime_bootstrap.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/sanitization_ollama_config.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/shell.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/signal_extraction_config.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/source_install.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/source_scrub.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/sources.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/sources_overview.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/sync.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/tool_index.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/ui_config.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/upgrades.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/usage.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/api/user_identity.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/canonicalization/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/canonicalization/mappers/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/canonicalization/mappers/base.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/canonicalization/mappers/demo_mappers.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/canonicalization/mappers/documents_mapper.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/canonicalization/mappers/github_activity_mapper.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/canonicalization/mappers/google_calendar_mapper.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/canonicalization/mappers/grok_mapper.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/canonicalization/mappers/transcript_mapper.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/canonicalization/models.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/canonicalization/resolver.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/cli/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/cli/__main__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/cli/assets/topos_black.png +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/cli/assets/topos_blk_rounded.png +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/cli/assets/topos_white.png +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/cli/commands.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/cli/profile_cmd.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/cli/reprocess_cmd.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/cli/setup_models_cmd.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/config/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/config/conversation_context_llm.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/config/facts_llm.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/config/local_model_builds.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/config/model_packs.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/config/node_function_providers.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/config/sanitization_ollama.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/config/settings.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/config/signal_extraction.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/config/uvicorn_logging.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/contacts/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/contacts/identity.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/api_models.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/connection_resilience.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/db_health.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/device_helpers.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/errors.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/events.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/aggregate.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/common.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/complexity.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/config.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/contacts_import.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/derivation.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/device.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/enrichment.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/enrichment_lab.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/filter_lab.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/graph_query.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/graph_summary.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/home_chat.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/mcp_client_elevations.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/mcp_clients.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/messages.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/messenger_analytics.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/registry.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/routines.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/timeline_daily.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/handlers/tool_index.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/logging.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/metrics.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/routine_access.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/startup_banner.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/state.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/table_layers.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/core/types.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/data_explorer_row_delete.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/defaults.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/disclosure/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/disclosure/canonical_writer.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/disclosure/field_registry.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/disclosure/privacy_layer.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/disclosure/tier.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/backends/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/backends/base.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/backends/generative_prompts.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/backends/generative_response.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/backends/huggingface.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/backends/ollama.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/backends/openai.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/backends/openai_compatible.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/backends/redpill.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/backends/stub.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/client.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/disk_space.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/engine.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/hosted_llm_wallet.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/intake.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/memory_utils.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/model_cache.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/model_manager.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/ollama_install.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/ollama_pull.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/ollama_runtime.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/ollama_setup_guidance.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/pipeline_memory.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/queue_manager.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/registration.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/result_formatter.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/router.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/scoped_token.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/tasks.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/torch_runtime.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/transport.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/usage_guard.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/usage_observation.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/engine/validator.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/catalog.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/derivation_recovery.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/job_readiness.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/_batch_limits.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/_engine_runner.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/attention_triage_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/availability_scores_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/complexity_snapshot_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/derivation_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/derived_object_embeddings_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/dimension_summary_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/fact_extraction_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/timeline_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/topic_clusters_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/raw/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/raw/language_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/model_overrides.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/models/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/models/manager.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/models/mvp_defaults.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/models/registry.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/models/versioning.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/pipeline_activity.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/processor.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/progress_bar.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/record_progress.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/registry_contract.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/signal_derivation_config.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment/source_overrides.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment_lab/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment_lab/bundles.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment_lab/model_resolve.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment_lab/schema.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment_lab/service.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment_lab/store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/enrichment_lab/worker.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/evals/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/evals/enrichment_eval.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/extensions.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/complexity/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/complexity/canonical.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/complexity/engine.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/complexity/entropy.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/complexity/focus.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/complexity/graph_metrics.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/complexity/influence.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/complexity/projection.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/complexity/snapshots.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/complexity/store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/complexity/topic_merge.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/complexity/topics.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/complexity/topics_daily.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/complexity/volatility.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/_scales.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/admin.legal.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/aspirations.goals.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/behavior.habits.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/behavior.preferences.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/beliefs.civic.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/beliefs.spiritual.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/communication.style.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/community.membership.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/craft.tooling.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/expertise.knowledge.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/finances.economics.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/health.lifestyle.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/health.mental.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/health.physical.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/household.pets.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/identity.core.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/interests.taste.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/life.events.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/narrative.self.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/net.capability.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/net.character.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/obligations.commitments.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/personality.traits.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/places.mobility.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/possessions.assets.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/relationships.social.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/values.motivation.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/vocab/dispositions.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/vocab/expertise.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/vocab/habits.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/vocab/interests.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/vocab/preferences.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/vocab/stances.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/vocab/tools.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/vocab/values.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/bundled_packs/work.career.yaml +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/candidates.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/commitments.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/guard.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/kernels.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/net_subject_policy.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/packs.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/person_bridge.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/person_reading.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/prefilter.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/registry.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/report_card.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/router.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/social_bench.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/social_kernels.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/synthesize.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/template.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/verify.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/derivation/writer.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/affinity.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/affinity_owner.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/affinity_quality.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/chatgpt_declared.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/community_names.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/community_naming.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/consolidation.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/context_vectors.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/cypher.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/declared_mappings.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/discourse_graph.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/dossier.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/edges.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/fact_materializer.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/graph_refresh.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/graph_search.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/linking.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/owner.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/entities/reads.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/facts/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/facts/reads.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/fit/evaluator.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/fit/opportunity_types.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/lifecycle/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/lifecycle/blackhole_rebuild.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/lifecycle/exclusions.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/lifecycle/gc.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/provenance/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/provenance/posture.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/brief_canonical_loader.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/brief_ontology.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/brief_renderer.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/brief_schemas.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/chunking.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/cluster_labels.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/conversation_context.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/conversation_windows.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/data_health.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/definitions/brief_ontologies.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/definitions/intentions.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/definitions/interests.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/definitions/memory.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/definitions/places.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/definitions/profile.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/definitions/relationships.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/definitions/resources.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/definitions/time.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/definitions/wellbeing.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/definitions/work.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/derived_index.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/derived_spec.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/dimension_briefs.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/dimension_definition_loader.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/dimension_profiles.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/dimension_registry.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/embed_context.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/extraction/artifact_router.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/extraction/artifact_store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/extraction/rule_extractors.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/graph_sanitize.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/hybrid_search.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/incremental_clustering.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/model_recommendations.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/query_embed_cache.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/schemas.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/service.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/signal_object_store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/source_hydration.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/structured_signal.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/tool_index.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/topic_clustering.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/typed_stores/aggregates.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/typed_stores/commitments.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/typed_stores/rhythm.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/vector_codec.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/vector_math.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/signal/vector_settings.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/stats/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/stats/definitions.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/stats/engine.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/stats/fold.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/stats/insights.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/timeline_projection.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/timeline_rollup.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/triage/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/triage/badges.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/triage/daily.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/triage/dashboard.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/triage/instruments.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/triage/intents.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/features/triage/readiness.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/filter_lab/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/filter_lab/bundles.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/filter_lab/schema.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/filter_lab/service.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/filter_lab/store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/filter_lab/worker.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/home_chat/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/home_chat/schema.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/home_chat/store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/hosted_pool_lease.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/checkpoints/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/inbox_crypto.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/inbox_drain.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/ingest_helpers.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/jobs.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/journal_location_fanout.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/journal_time_log_normalize.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/local_exports.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/local_sync_jobs.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/log_preview.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/manager.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parser.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parsers/base.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parsers/browser_parser.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parsers/calendar_parser.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parsers/chatgpt_export.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parsers/documents_parser.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parsers/github_activity_parser.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parsers/google_calendar_parser.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parsers/grok_parser.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parsers/transcript_parser.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/parsers/voxterm_parser.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/progress.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/sources/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/sources/base.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/sources/calendar.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/sources/chatgpt.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/sources/contact_importers.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/sources/grok.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/state_machine.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/triggers/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/triggers/file_trigger.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/usage_inbox_dedupe.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/validation/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/validation/base.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/validation/schema_registry.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/ingestion/validation/schema_validator.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/lineage/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/lineage/provenance.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/lineage/tracker.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/llm_integrations_storage.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/mcp_clients.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/mcp_stdio_proxy.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/observability/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/observability/alerts.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/observability/metrics.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/observability/tracing.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/openai_client.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/owner_key.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/pipeline/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/pipeline/audit.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/pipeline/envelope.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/pipeline/stages.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/pipeline/stub_enqueue.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/principal.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/profiles.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/projections/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/projections/vector_index/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/projections/vector_index/base.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/projections/vector_index/builders.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/projections/vector_index/health_checks.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/protocol/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/protocol/narrowing_vocabulary.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/protocol/query_field_contract.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/protocol/retrieval_text_contract.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/audit.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/closeness.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/cohort_resolvers.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/collaborators.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/ddr.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/entity_window.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/facts_direct.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/fingerprint.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/game_layer.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/grant_cache.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/graph_lane.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/intent.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/journal_event_lane.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/minimizer.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/narrowing.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/negotiation.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/overheard.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/packet_resolution.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/planner.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/runtime.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/scope_arbiter.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/scope_classifier.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/scope_head.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/scope_registry.json +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/scope_registry_loader.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/scope_shadow.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/session.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/session_utils.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/source_generation.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/truth_facts.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/truth_prompts.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/turn_classifier.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/verify.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/query/verify_modes.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/rate_limit.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/relay_stamp.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/routines/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/routines/schema.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/routines/store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/runtime_housekeeping.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/runtime_update.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sanitization/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sanitization/nsfw_classifier.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sanitization/ollama_transforms.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sanitization/prewarm.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sanitization/privacy_filter.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/scope_resolution.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/services/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/services/container.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/services/embeddings/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/services/embeddings/base.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/services/embeddings/local.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/services/embeddings/remote.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/services/interfaces.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/services/llm/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/services/llm/base.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/services/llm/openai.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/services/local.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/services/postgres.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sources/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sources/bundled_canonical_triples.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sources/canonical_signal_defaults.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sources/declared_field_map_spec.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sources/definitions.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sources/registry.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sources/runtime_install.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sources/scrub_attribution.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/startup_banner.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/adapters/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/adapters/factory.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/adapters/fakes.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/adapters/postgres/stores.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/adapters/protocols.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/adapters/sqlite/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/adapters/sqlite/vector_search.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/canonical/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/canonical/activity_tables.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/canonical/ai_chat/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/canonical/ai_chat/canonicalizer.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/canonical/ai_chat/mapper.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/canonical/ai_chat/model.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/canonical/ai_chat/tables.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/canonical/journal_repair.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/canonical/mapping_store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/canonical/postgres.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/client.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/connection_tuning.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/actor_role_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/affinity_pair_labels_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/attention_triage_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/attention_triage_v2.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/backup.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/backup_custody.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/calendar_events_scheduling_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/community_names_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/complexity_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/conflict_provenance_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/conversation_context_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/derivation_factory_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/derivation_provenance_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/derived_row_identity_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/documents_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/enrichment_record_progress_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/enrichment_spec_version_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/entity_affinity_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/entity_blackhole_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/entity_context_vectors_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/entity_context_vectors_v2.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/entity_mentions_authored_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/entity_review_candidate_bar_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/entity_review_dedup_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/entity_review_provenance_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/episodes_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/fact_dimension_by_entity_type_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/journal_origin_dimension_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/mention_table_stamp_backfill_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/message_emotions_role_backfill_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/message_emotions_role_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/net_subject_policy_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/pack_registry_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/pipeline_jobs_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/query_artifacts_duration_ms_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/remediation_person_model.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/retire_url_classification_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/scope_source_generation.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/signal_objects.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/signal_summaries_drop_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/transcripts_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/paths.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/postgres.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/schema.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/schema_probe.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/db/storage_breakdown.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/derived_row_identity.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/enrichment/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/normalized/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/normalized/normalized_store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/oplog/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/oplog/decision.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/oplog/oplog_store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/oplog/postgres.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/person/identity_resolver.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/projections/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/projections/index_ops_store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/projections/vector_index_store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/raw/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/raw/browser_flat_tables.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/raw/file_store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/raw/raw_store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/raw/raw_tables_manager.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/raw/sqlite_raw_store.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/security/encryption.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/signal_identity.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/source_settings.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/storage/user_identity.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sync/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sync/client.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/sync_handlers.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/testing/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/testing/lifespan.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/uds.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/uma_contact_enrichment.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/uma_resource_id.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/uma_rpt.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/upgrades/__init__.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/utils/base_object.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos/websocket_client.py +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos_node.egg-info/dependency_links.txt +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos_node.egg-info/entry_points.txt +0 -0
- {topos_node-1.3.56 → topos_node-1.4.0}/topos_node.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: topos-node
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: Topos personal AI engine (FastAPI): local data, sync, control plane WebSocket client
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Project-URL: Homepage, https://topos.dialogues.ai
|
|
@@ -63,6 +63,7 @@ Provides-Extra: dev
|
|
|
63
63
|
Requires-Dist: pytest~=9.0.3; extra == "dev"
|
|
64
64
|
Requires-Dist: pytest-asyncio~=1.3.0; extra == "dev"
|
|
65
65
|
Requires-Dist: httpx~=0.28.1; extra == "dev"
|
|
66
|
+
Requires-Dist: hypothesis<7,>=6.100; extra == "dev"
|
|
66
67
|
Dynamic: license-file
|
|
67
68
|
|
|
68
69
|
<div align="center">
|
|
@@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta"
|
|
|
9
9
|
|
|
10
10
|
[project]
|
|
11
11
|
name = "topos-node"
|
|
12
|
-
version = "1.
|
|
12
|
+
version = "1.4.0"
|
|
13
13
|
description = "Topos personal AI engine (FastAPI): local data, sync, control plane WebSocket client"
|
|
14
14
|
readme = "README.md"
|
|
15
15
|
license = "Apache-2.0"
|
|
@@ -109,6 +109,7 @@ dev = [
|
|
|
109
109
|
"pytest~=9.0.3",
|
|
110
110
|
"pytest-asyncio~=1.3.0",
|
|
111
111
|
"httpx~=0.28.1",
|
|
112
|
+
"hypothesis>=6.100,<7",
|
|
112
113
|
]
|
|
113
114
|
|
|
114
115
|
[project.scripts]
|
|
@@ -168,6 +169,8 @@ markers = [
|
|
|
168
169
|
"bhlr: black-hole leak-rate probe (entity black hole); tier-1 CI gate, must find zero leaks",
|
|
169
170
|
"eval_nightly: statistical privacy eval (attacker advantage, minimality, latency); nightly",
|
|
170
171
|
"eval_release: release-tier privacy eval (negotiation A/B, Pareto); run per release",
|
|
172
|
+
"fuzz: the permissions v2 property-based lane (Hypothesis; confidence program C5)",
|
|
173
|
+
"ordinal_ids_retired: run with p2a-v1/v2 releases refused, as the node does (tests/permissions_v2/conftest.py)",
|
|
171
174
|
]
|
|
172
175
|
pythonpath = ["tests/gap/p3/engine", "tests/gap/p4/engine", "tests/gap/qq/engine", "tests/acceptance/wiki_mvp", "tests/evals/time_signal"]
|
|
173
176
|
testpaths = ["tests"]
|
|
@@ -5,7 +5,7 @@ from datetime import datetime
|
|
|
5
5
|
from enum import Enum
|
|
6
6
|
from typing import Any, Dict, Iterable, List, Literal, Optional
|
|
7
7
|
|
|
8
|
-
from pydantic import BaseModel, Field, field_validator, model_validator
|
|
8
|
+
from pydantic import BaseModel, Field, StrictStr, field_validator, model_validator
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class FilterCategory(str, Enum):
|
|
@@ -530,6 +530,31 @@ class FilterManifest(BaseModel):
|
|
|
530
530
|
manifest_version: int = Field(1, ge=1)
|
|
531
531
|
filters: List[FilterInstance] = Field(default_factory=list)
|
|
532
532
|
provenance: Optional[FilterManifestProvenance] = None
|
|
533
|
+
access_mode_ceiling: Optional[Literal["summary", "inference", "raw"]] = None
|
|
534
|
+
scope_table_allowlist: Optional[Dict[StrictStr, List[StrictStr]]] = None
|
|
535
|
+
|
|
536
|
+
@field_validator("access_mode_ceiling", mode="before")
|
|
537
|
+
@classmethod
|
|
538
|
+
def normalize_ceiling(cls, value: Any) -> Any:
|
|
539
|
+
# Mirror of the control plane's validator (ported from the held sharing
|
|
540
|
+
# hotfix 1dd65995; BEFORE_PROD_REVIEW P0-10). The query lane decodes stored
|
|
541
|
+
# grant envelopes through this model (topos/uma_filters.query_filter_manifest),
|
|
542
|
+
# so a stored ceiling whose spelling differs would otherwise raise here and
|
|
543
|
+
# fail that grant's reads instead of being read as the ceiling it names.
|
|
544
|
+
if isinstance(value, str):
|
|
545
|
+
value = value.strip().lower()
|
|
546
|
+
return value or None
|
|
547
|
+
return value
|
|
548
|
+
|
|
549
|
+
@field_validator("scope_table_allowlist")
|
|
550
|
+
@classmethod
|
|
551
|
+
def validate_scope_table_allowlist(cls, value):
|
|
552
|
+
if value is None:
|
|
553
|
+
return None
|
|
554
|
+
for scope, tables in value.items():
|
|
555
|
+
if not scope or scope != scope.strip() or any(not table or table != table.strip() for table in tables):
|
|
556
|
+
raise ValueError("scope/table IDs must be nonempty canonical strings")
|
|
557
|
+
return {scope: sorted(set(tables)) for scope, tables in value.items()}
|
|
533
558
|
|
|
534
559
|
def to_storage_dict(self) -> Dict[str, Any]:
|
|
535
560
|
return self.model_dump(exclude_none=True, mode="json")
|
|
@@ -591,21 +616,11 @@ def _merge_param_values(filter_id: str, existing: Dict[str, Any], incoming: Dict
|
|
|
591
616
|
if end is None or str(incoming_end) < str(end):
|
|
592
617
|
merged["end"] = incoming_end
|
|
593
618
|
return merged
|
|
594
|
-
if filter_id
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
elif incoming_values:
|
|
600
|
-
merged["source_ids"] = sorted(incoming_values)
|
|
601
|
-
return merged
|
|
602
|
-
if filter_id == "column_allowlist":
|
|
603
|
-
current = set(str(item) for item in merged.get("fields", []))
|
|
604
|
-
incoming_values = set(str(item) for item in incoming.get("fields", []))
|
|
605
|
-
if current and incoming_values:
|
|
606
|
-
merged["fields"] = sorted(current & incoming_values)
|
|
607
|
-
elif incoming_values:
|
|
608
|
-
merged["fields"] = sorted(incoming_values)
|
|
619
|
+
if filter_id in {"source_filter", "column_allowlist"}:
|
|
620
|
+
key = "source_ids" if filter_id == "source_filter" else "fields"
|
|
621
|
+
# These are validated, required lists. Missing the entire filter means
|
|
622
|
+
# unrestricted; a present empty list is bottom and absorbs every meet.
|
|
623
|
+
merged[key] = sorted(set(merged[key]) & set(incoming[key]))
|
|
609
624
|
return merged
|
|
610
625
|
if filter_id == "column_blocklist":
|
|
611
626
|
current = set(str(item) for item in merged.get("fields", []))
|
|
@@ -650,9 +665,20 @@ def merge_filter_manifests(
|
|
|
650
665
|
provenance: Optional[FilterManifestProvenance] = None,
|
|
651
666
|
) -> FilterManifest:
|
|
652
667
|
merged_instances: Dict[str, FilterInstance] = {}
|
|
668
|
+
ceiling = None
|
|
669
|
+
table_allowlist = None
|
|
653
670
|
for manifest in manifests:
|
|
654
671
|
if manifest is None:
|
|
655
672
|
continue
|
|
673
|
+
if manifest.access_mode_ceiling is not None:
|
|
674
|
+
ranks = {"summary": 0, "inference": 1, "raw": 2}
|
|
675
|
+
if ceiling is None or ranks[manifest.access_mode_ceiling] < ranks[ceiling]:
|
|
676
|
+
ceiling = manifest.access_mode_ceiling
|
|
677
|
+
if manifest.scope_table_allowlist is not None:
|
|
678
|
+
if table_allowlist is None:
|
|
679
|
+
table_allowlist = {}
|
|
680
|
+
for scope, tables in manifest.scope_table_allowlist.items():
|
|
681
|
+
table_allowlist[scope] = sorted(set(tables) & set(table_allowlist[scope])) if scope in table_allowlist else sorted(set(tables))
|
|
656
682
|
for item in manifest.filters:
|
|
657
683
|
key = _manifest_merge_key(item)
|
|
658
684
|
existing = merged_instances.get(key)
|
|
@@ -667,4 +693,6 @@ def merge_filter_manifests(
|
|
|
667
693
|
return FilterManifest(
|
|
668
694
|
filters=sorted(merged_instances.values(), key=lambda item: (_manifest_merge_key(item), item.filter_id)),
|
|
669
695
|
provenance=provenance,
|
|
696
|
+
access_mode_ceiling=ceiling,
|
|
697
|
+
scope_table_allowlist=table_allowlist,
|
|
670
698
|
)
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
"""The default test lane must not touch anything under the owner's ``~/.topos``.
|
|
2
|
+
|
|
3
|
+
``test_owner_database_hermeticity.py`` covers the database. This covers the rest of
|
|
4
|
+
the directory: ``.env`` (identity, and since the dual-mint the owner key),
|
|
5
|
+
``engine.sock`` (the owner socket the running node serves), ``cp_stamp_key.pub``,
|
|
6
|
+
``ingestion/``, the active-profile marker and the logs.
|
|
7
|
+
|
|
8
|
+
The hazard this file was written against (2026-09-18, MERGE_REHEARSAL.md §2.8
|
|
9
|
+
items 4-5): ``tests/topos/test_engine_presence_messages.py`` starts the app with a
|
|
10
|
+
control-plane URL, so the lifespan's dual-mint runs ``ensure_owner_key``. No
|
|
11
|
+
conftest set ``TOPOS_ENV_FILE``, so that READ the owner's real ``~/.topos/.env`` and
|
|
12
|
+
appended a minted ``TOPOS_OWNER_KEY`` when none was there. The same lifespan bound
|
|
13
|
+
the owner socket at ``~/.topos/engine.sock``. The live-DB guard never fired,
|
|
14
|
+
because it watches ``sqlite3.connect`` and nothing else. And the minted key stayed
|
|
15
|
+
in ``os.environ`` and on the settings singleton, so every later test ran in owner
|
|
16
|
+
mode.
|
|
17
|
+
|
|
18
|
+
Every test here runs under a SCRATCH home. A hermeticity test that had to look at
|
|
19
|
+
the real ``~/.topos`` to prove itself would be the bug it is guarding against.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import hashlib
|
|
25
|
+
import os
|
|
26
|
+
import socket
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
|
|
29
|
+
import pytest
|
|
30
|
+
|
|
31
|
+
from tests import live_db_watch
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _tree(root: Path) -> dict[str, tuple[str, int]]:
|
|
35
|
+
"""Every path under ``root`` -> (content digest, mtime_ns). Sockets by kind."""
|
|
36
|
+
out: dict[str, tuple[str, int]] = {}
|
|
37
|
+
if not root.exists():
|
|
38
|
+
return out
|
|
39
|
+
for p in sorted(root.rglob("*")):
|
|
40
|
+
st = p.lstat()
|
|
41
|
+
rel = str(p.relative_to(root))
|
|
42
|
+
if p.is_socket():
|
|
43
|
+
out[rel] = ("<socket>", st.st_mtime_ns)
|
|
44
|
+
elif p.is_file():
|
|
45
|
+
out[rel] = (hashlib.sha256(p.read_bytes()).hexdigest(), st.st_mtime_ns)
|
|
46
|
+
else:
|
|
47
|
+
out[rel] = ("<dir>", 0)
|
|
48
|
+
return out
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@pytest.fixture
|
|
52
|
+
def scratch_home(monkeypatch: pytest.MonkeyPatch):
|
|
53
|
+
"""A home directory that looks like a developer's with a node on it.
|
|
54
|
+
|
|
55
|
+
Seeded with a ``.topos/.env`` that holds a TOPOS_KEY and NO owner key: exactly
|
|
56
|
+
the file the dual-mint appends to. HOME and ``Path.home`` both point here, so a
|
|
57
|
+
default that is not pinned lands in this tree instead of the real one, where
|
|
58
|
+
the test can see it.
|
|
59
|
+
|
|
60
|
+
Under /tmp, not tmp_path. macOS caps an AF_UNIX path at 104 bytes, and
|
|
61
|
+
``<tmp_path>/.topos/engine.sock`` is longer, so under tmp_path an unpinned
|
|
62
|
+
owner socket fails to bind (silently, on the supervisor thread) and this
|
|
63
|
+
fixture would miss exactly the write it exists to see.
|
|
64
|
+
"""
|
|
65
|
+
import shutil
|
|
66
|
+
import tempfile
|
|
67
|
+
|
|
68
|
+
home = Path(tempfile.mkdtemp(prefix="th-", dir="/tmp")).resolve()
|
|
69
|
+
(home / ".topos").mkdir(parents=True)
|
|
70
|
+
(home / ".topos" / ".env").write_text("TOPOS_KEY=tk_scratch_not_real\n")
|
|
71
|
+
# Keep Hugging Face on the real cache: a scratch HOME is otherwise a cold
|
|
72
|
+
# cache, and startup's scope-head warm downloads the head again (~100s).
|
|
73
|
+
monkeypatch.setenv(
|
|
74
|
+
"HF_HOME",
|
|
75
|
+
os.environ.get("HF_HOME") or str(live_db_watch.REAL_HOME / ".cache" / "huggingface"),
|
|
76
|
+
)
|
|
77
|
+
monkeypatch.setenv("HOME", str(home))
|
|
78
|
+
monkeypatch.setattr(Path, "home", classmethod(lambda cls: home))
|
|
79
|
+
yield home
|
|
80
|
+
shutil.rmtree(home, ignore_errors=True)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
async def _tree_after_settling(root: Path, before: dict, seconds: float = 3.0) -> dict:
|
|
84
|
+
"""The tree once background startup threads had a chance to act.
|
|
85
|
+
|
|
86
|
+
The owner socket is bound by a supervisor THREAD (``topos.uds``), usually
|
|
87
|
+
after the lifespan has already returned, so an immediate snapshot misses it.
|
|
88
|
+
Returns as soon as anything changed; waits the full ``seconds`` otherwise.
|
|
89
|
+
"""
|
|
90
|
+
import asyncio
|
|
91
|
+
import time
|
|
92
|
+
|
|
93
|
+
deadline = time.monotonic() + seconds
|
|
94
|
+
while True:
|
|
95
|
+
now = _tree(root)
|
|
96
|
+
if now != before or time.monotonic() >= deadline:
|
|
97
|
+
return now
|
|
98
|
+
await asyncio.sleep(0.05)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _fresh_owner_state() -> None:
|
|
102
|
+
"""The state a developer's machine starts a test run in: no owner key anywhere.
|
|
103
|
+
|
|
104
|
+
Deliberately NOT through monkeypatch. Monkeypatch would put the previous values
|
|
105
|
+
back at teardown and hide the leak this file is also about; restoring owner
|
|
106
|
+
state is the conftest's job, and ``test_owner_mode_did_not_leak_*`` below checks
|
|
107
|
+
it did it.
|
|
108
|
+
"""
|
|
109
|
+
from topos.config.settings import settings
|
|
110
|
+
|
|
111
|
+
os.environ.pop("TOPOS_OWNER_KEY", None)
|
|
112
|
+
settings.topos_owner_key = None
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
async def _run_lifespan(monkeypatch: pytest.MonkeyPatch, tmp_path: Path, *, with_cp: bool) -> None:
|
|
116
|
+
from topos import app as app_module
|
|
117
|
+
from topos.config.settings import settings
|
|
118
|
+
from topos.testing.lifespan import LifespanManager
|
|
119
|
+
|
|
120
|
+
class _FakeControlPlaneClient:
|
|
121
|
+
def __init__(self, control_plane_url, api_key, handler, verify_ssl=True):
|
|
122
|
+
del control_plane_url, api_key, handler, verify_ssl
|
|
123
|
+
|
|
124
|
+
def start(self) -> None:
|
|
125
|
+
pass
|
|
126
|
+
|
|
127
|
+
async def stop(self) -> None:
|
|
128
|
+
pass
|
|
129
|
+
|
|
130
|
+
async def send_message(self, message) -> None:
|
|
131
|
+
del message
|
|
132
|
+
|
|
133
|
+
monkeypatch.setattr(
|
|
134
|
+
settings, "control_plane_url", "ws://example.test/ws/engine" if with_cp else None,
|
|
135
|
+
raising=False,
|
|
136
|
+
)
|
|
137
|
+
monkeypatch.setattr(settings, "topos_database_path", str(tmp_path / "engine.db"))
|
|
138
|
+
monkeypatch.setattr(app_module, "ControlPlaneClient", _FakeControlPlaneClient)
|
|
139
|
+
async with LifespanManager(app_module.app):
|
|
140
|
+
pass
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def test_conftest_pins_every_topos_home_default_outside_any_home() -> None:
|
|
144
|
+
"""The pins exist, and none of them points into a home directory."""
|
|
145
|
+
from tests import topos_home_pin
|
|
146
|
+
|
|
147
|
+
real_topos = os.path.realpath(os.path.join(live_db_watch.REAL_HOME, ".topos"))
|
|
148
|
+
pinned = topos_home_pin.pinned_paths()
|
|
149
|
+
for env_name in topos_home_pin.PINNED_ENV:
|
|
150
|
+
value = os.environ.get(env_name)
|
|
151
|
+
assert value, f"{env_name} is not pinned"
|
|
152
|
+
assert os.path.realpath(value) == os.path.realpath(pinned[env_name]), env_name
|
|
153
|
+
assert not os.path.realpath(value).startswith(real_topos + os.sep), (env_name, value)
|
|
154
|
+
|
|
155
|
+
from topos import owner_key, relay_stamp, uds
|
|
156
|
+
from topos.storage.raw.file_store import active_ingestion_base
|
|
157
|
+
|
|
158
|
+
assert owner_key._env_path() == Path(pinned["TOPOS_ENV_FILE"])
|
|
159
|
+
assert uds.socket_path() == Path(pinned["TOPOS_UDS_PATH"])
|
|
160
|
+
assert active_ingestion_base() == Path(pinned["TOPOS_INGESTION_BASE_PATH"])
|
|
161
|
+
assert Path(os.path.expanduser(relay_stamp._PINNED_KEY_PATH)).is_relative_to(
|
|
162
|
+
topos_home_pin.pinned_root()
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@pytest.mark.asyncio
|
|
167
|
+
async def test_presence_lifespan_with_a_control_plane_leaves_home_untouched(
|
|
168
|
+
scratch_home: Path, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
169
|
+
) -> None:
|
|
170
|
+
"""The exact hazard: control-plane URL set -> dual-mint -> ensure_owner_key.
|
|
171
|
+
|
|
172
|
+
Before the fix this appended ``TOPOS_OWNER_KEY=`` to ``$HOME/.topos/.env`` and
|
|
173
|
+
bound ``$HOME/.topos/engine.sock``.
|
|
174
|
+
"""
|
|
175
|
+
_fresh_owner_state()
|
|
176
|
+
before = _tree(scratch_home)
|
|
177
|
+
await _run_lifespan(monkeypatch, tmp_path, with_cp=True)
|
|
178
|
+
after = await _tree_after_settling(scratch_home, before)
|
|
179
|
+
assert after == before, {
|
|
180
|
+
"created": sorted(set(after) - set(before)),
|
|
181
|
+
"changed": sorted(k for k in before if k in after and after[k] != before[k]),
|
|
182
|
+
"removed": sorted(set(before) - set(after)),
|
|
183
|
+
}
|
|
184
|
+
assert "TOPOS_OWNER_KEY" not in (scratch_home / ".topos" / ".env").read_text()
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
@pytest.mark.asyncio
|
|
188
|
+
async def test_plain_lifespan_leaves_home_untouched(
|
|
189
|
+
scratch_home: Path, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
190
|
+
) -> None:
|
|
191
|
+
"""A full lifespan start with no control plane touches nothing under HOME either."""
|
|
192
|
+
before = _tree(scratch_home)
|
|
193
|
+
await _run_lifespan(monkeypatch, tmp_path, with_cp=False)
|
|
194
|
+
after = await _tree_after_settling(scratch_home, before)
|
|
195
|
+
assert after == before, {
|
|
196
|
+
"created": sorted(set(after) - set(before)),
|
|
197
|
+
"changed": sorted(k for k in before if k in after and after[k] != before[k]),
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
@pytest.mark.asyncio
|
|
202
|
+
async def test_owner_mode_leak_setup_mints_a_key(
|
|
203
|
+
scratch_home: Path, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
204
|
+
) -> None:
|
|
205
|
+
"""First half of a pair: arm owner mode the way the presence test does.
|
|
206
|
+
|
|
207
|
+
The mint lands in the PINNED env file (so this also proves the pin is what
|
|
208
|
+
``ensure_owner_key`` reads), and the key is left on the process exactly as the
|
|
209
|
+
lifespan leaves it. The next test checks the conftest took it back off.
|
|
210
|
+
"""
|
|
211
|
+
from tests import topos_home_pin
|
|
212
|
+
from topos.config.settings import settings
|
|
213
|
+
|
|
214
|
+
_fresh_owner_state()
|
|
215
|
+
await _run_lifespan(monkeypatch, tmp_path, with_cp=True)
|
|
216
|
+
assert settings.topos_owner_key, "the dual-mint did not run; this pair proves nothing"
|
|
217
|
+
assert os.environ.get("TOPOS_OWNER_KEY") == settings.topos_owner_key
|
|
218
|
+
pinned_env = Path(topos_home_pin.pinned_paths()["TOPOS_ENV_FILE"])
|
|
219
|
+
assert f"TOPOS_OWNER_KEY={settings.topos_owner_key}" in pinned_env.read_text()
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def test_owner_mode_did_not_leak_out_of_the_previous_test() -> None:
|
|
223
|
+
"""Second half. Runs after the one above (file order); alone it passes trivially.
|
|
224
|
+
|
|
225
|
+
Before the fix two ``tests/topos/test_ingestion_sources.py`` tests got 403
|
|
226
|
+
``owner_mode_required`` on the beta lineage because this was still set.
|
|
227
|
+
"""
|
|
228
|
+
from topos.config.settings import settings
|
|
229
|
+
|
|
230
|
+
assert not settings.topos_owner_key
|
|
231
|
+
assert "TOPOS_OWNER_KEY" not in os.environ
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
# -- the widened guard: any file operation under ~/.topos, not only sqlite ---------
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def test_the_file_guard_watches_the_real_topos_home() -> None:
|
|
238
|
+
"""Snapshotted from the real home at import, before any test can move HOME."""
|
|
239
|
+
assert live_db_watch.file_guard_is_installed()
|
|
240
|
+
real = os.path.realpath(os.path.join(os.path.expanduser("~"), ".topos"))
|
|
241
|
+
# This test runs under the real HOME, so the two must agree.
|
|
242
|
+
assert real in live_db_watch.watched_roots()
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
@pytest.mark.parametrize(
|
|
246
|
+
"operation, kind",
|
|
247
|
+
[
|
|
248
|
+
(lambda root: (root / ".env").read_text(), "read"),
|
|
249
|
+
(lambda root: (root / ".env").open("a").write("X=1\n"), "write"),
|
|
250
|
+
(lambda root: os.open(root / "new", os.O_WRONLY | os.O_CREAT), "write"),
|
|
251
|
+
(lambda root: os.open(root / ".env", os.O_RDONLY), "read"),
|
|
252
|
+
(lambda root: (root / "sub").mkdir(), "write"),
|
|
253
|
+
(lambda root: os.replace(root / ".env", root / "moved"), "write"),
|
|
254
|
+
(lambda root: os.remove(root / ".env"), "write"),
|
|
255
|
+
(lambda root: os.chmod(root / ".env", 0o600), "write"),
|
|
256
|
+
],
|
|
257
|
+
ids=["read_text", "append", "os.open-create", "os.open-read", "mkdir", "replace", "remove", "chmod"],
|
|
258
|
+
)
|
|
259
|
+
def test_any_file_operation_under_owner_data_is_refused_and_recorded(
|
|
260
|
+
tmp_path: Path, operation, kind: str
|
|
261
|
+
) -> None:
|
|
262
|
+
"""Against a throwaway root armed as owner data, never the real one."""
|
|
263
|
+
root = tmp_path / "pretend-topos"
|
|
264
|
+
root.mkdir()
|
|
265
|
+
(root / ".env").write_text("TOPOS_KEY=tk_scratch_not_real\n")
|
|
266
|
+
before = _tree(root)
|
|
267
|
+
with live_db_watch.watching_root(root) as capture:
|
|
268
|
+
with pytest.raises(PermissionError) as excinfo:
|
|
269
|
+
operation(root)
|
|
270
|
+
found = capture.captured()
|
|
271
|
+
assert _tree(root) == before, "the refusal must land BEFORE the operation"
|
|
272
|
+
assert live_db_watch.ALLOW_ENV in str(excinfo.value)
|
|
273
|
+
assert len(found) == 1, found
|
|
274
|
+
assert found[0].kind == kind
|
|
275
|
+
assert found[0].path.startswith(os.path.realpath(root))
|
|
276
|
+
assert __file__ in found[0].origin
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def test_binding_a_unix_socket_under_owner_data_is_refused() -> None:
|
|
280
|
+
"""The owner socket: binding one where the running node serves its own.
|
|
281
|
+
|
|
282
|
+
Under /tmp, not tmp_path: macOS caps an AF_UNIX path at 104 bytes and checks
|
|
283
|
+
that before the audit event fires, so a long tmp_path proves nothing.
|
|
284
|
+
"""
|
|
285
|
+
import shutil
|
|
286
|
+
import tempfile
|
|
287
|
+
|
|
288
|
+
root = Path(tempfile.mkdtemp(prefix="th-", dir="/tmp")).resolve()
|
|
289
|
+
try:
|
|
290
|
+
with live_db_watch.watching_root(root) as capture:
|
|
291
|
+
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
292
|
+
try:
|
|
293
|
+
with pytest.raises(PermissionError):
|
|
294
|
+
s.bind(str(root / "e.sock"))
|
|
295
|
+
finally:
|
|
296
|
+
s.close()
|
|
297
|
+
found = capture.captured()
|
|
298
|
+
assert not (root / "e.sock").exists()
|
|
299
|
+
assert [f.kind for f in found] == ["write"]
|
|
300
|
+
finally:
|
|
301
|
+
shutil.rmtree(root, ignore_errors=True)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def test_operations_outside_owner_data_are_not_recorded(tmp_path: Path) -> None:
|
|
305
|
+
root = tmp_path / "pretend-topos"
|
|
306
|
+
root.mkdir()
|
|
307
|
+
elsewhere = tmp_path / "elsewhere.txt"
|
|
308
|
+
with live_db_watch.watching_root(root) as capture:
|
|
309
|
+
elsewhere.write_text("fine")
|
|
310
|
+
elsewhere.read_text()
|
|
311
|
+
found = capture.captured()
|
|
312
|
+
assert found == []
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def test_the_opt_out_downgrades_the_file_guard_to_recording(
|
|
316
|
+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
317
|
+
) -> None:
|
|
318
|
+
"""Same escape hatch as the database guard: record everything, refuse nothing."""
|
|
319
|
+
root = tmp_path / "pretend-topos"
|
|
320
|
+
root.mkdir()
|
|
321
|
+
monkeypatch.setenv(live_db_watch.ALLOW_ENV, "1")
|
|
322
|
+
with live_db_watch.watching_root(root) as capture:
|
|
323
|
+
(root / "x").write_text("allowed")
|
|
324
|
+
found = capture.captured()
|
|
325
|
+
assert (root / "x").read_text() == "allowed"
|
|
326
|
+
assert [f.refused for f in found] == [False]
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from fastapi import APIRouter, Body, Depends, HTTPException, Request
|
|
4
4
|
|
|
5
|
-
from ..auth import require_api_key
|
|
5
|
+
from ..auth import require_api_key, require_owner_unless_legacy
|
|
6
6
|
from ..ingestion.reprocess import reprocess_source
|
|
7
7
|
from .ingestion_sources import ingest_source
|
|
8
8
|
|
|
@@ -19,7 +19,7 @@ async def report_progress() -> dict:
|
|
|
19
19
|
return {"status": "stub"}
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
@router.post("/ingestion/reprocess", dependencies=[Depends(
|
|
22
|
+
@router.post("/ingestion/reprocess", dependencies=[Depends(require_owner_unless_legacy)])
|
|
23
23
|
async def ingestion_reprocess(payload: dict = Body(default_factory=dict)) -> dict:
|
|
24
24
|
"""Re-run raw→canonical for a source (optional newest-N via ``limit``).
|
|
25
25
|
|
|
@@ -8,7 +8,7 @@ from typing import Optional
|
|
|
8
8
|
|
|
9
9
|
from fastapi import APIRouter, Body, Depends, Query, Request # noqa: F401 Body used in put_signal_settings
|
|
10
10
|
|
|
11
|
-
from ..auth import require_api_key
|
|
11
|
+
from ..auth import require_api_key, require_owner_unless_legacy
|
|
12
12
|
from ..core.state import get_db_connection
|
|
13
13
|
from ..ingestion.ingest_helpers import ingest_file_payload, ingest_ui_payload, resolve_file_format
|
|
14
14
|
from ..ingestion.local_sync import run_signal_upload
|
|
@@ -191,7 +191,7 @@ async def put_source_settings_endpoint(
|
|
|
191
191
|
return {"status": "ok", "dataset_id": dataset_id, "source_id": source_id, **settings}
|
|
192
192
|
|
|
193
193
|
|
|
194
|
-
@router.post("/sources/{source_id}/sync", dependencies=[Depends(
|
|
194
|
+
@router.post("/sources/{source_id}/sync", dependencies=[Depends(require_owner_unless_legacy)])
|
|
195
195
|
async def sync_source(
|
|
196
196
|
source_id: str,
|
|
197
197
|
dataset_id: Optional[str] = Query(default=None, description="Dataset/owner scope for checkpoint and messages"),
|
|
@@ -262,7 +262,7 @@ async def get_job_progress(job_id: str):
|
|
|
262
262
|
return {"status": "ok", **_progress_dict(job)}
|
|
263
263
|
|
|
264
264
|
|
|
265
|
-
@router.post("/sources/signal/upload", dependencies=[Depends(
|
|
265
|
+
@router.post("/sources/signal/upload", dependencies=[Depends(require_owner_unless_legacy)])
|
|
266
266
|
async def upload_signal_export(
|
|
267
267
|
request: Request,
|
|
268
268
|
dataset_id: Optional[str] = Query(default=None),
|
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import uuid
|
|
6
6
|
|
|
7
|
-
from fastapi import APIRouter, Body, Depends
|
|
7
|
+
from fastapi import APIRouter, Body, Depends, HTTPException
|
|
8
8
|
|
|
9
9
|
from ..auth import resolve_request_principal
|
|
10
10
|
from ..core.handlers import handle_control_plane_request
|
|
@@ -20,6 +20,22 @@ def _local_mcp_payload(extra: dict | None = None) -> dict:
|
|
|
20
20
|
return p
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
def _truth_door(msg_type: str):
|
|
24
|
+
"""The truth routes' principal dependency: the handler's own door decision
|
|
25
|
+
(topos/query/truth_door.py), answered as an HTTP 403 before the route reads
|
|
26
|
+
the body instead of a 200 error body after it."""
|
|
27
|
+
|
|
28
|
+
def admitted(principal=Depends(resolve_request_principal)): # noqa: B008
|
|
29
|
+
from ..query.truth_door import truth_door_refusal
|
|
30
|
+
|
|
31
|
+
refused = truth_door_refusal(principal, msg_type)
|
|
32
|
+
if refused:
|
|
33
|
+
raise HTTPException(status_code=refused["code"], detail=refused["error"])
|
|
34
|
+
return principal
|
|
35
|
+
|
|
36
|
+
return admitted
|
|
37
|
+
|
|
38
|
+
|
|
23
39
|
@router.post("/list_database_tables")
|
|
24
40
|
async def local_list_database_tables(principal=Depends(resolve_request_principal)) -> dict: # noqa: B008
|
|
25
41
|
"""List tables (same as CP-forwarded tool). Requires Bearer TOPOS_KEY."""
|
|
@@ -33,12 +49,14 @@ async def local_list_database_tables(principal=Depends(resolve_request_principal
|
|
|
33
49
|
@router.post("/verify_claim")
|
|
34
50
|
async def local_verify_claim(
|
|
35
51
|
body: dict = Body(default_factory=dict),
|
|
36
|
-
principal=Depends(
|
|
52
|
+
principal=Depends(_truth_door("verify_claim")), # noqa: B008
|
|
37
53
|
) -> dict:
|
|
38
|
-
"""Same-device truth check (PLAN_TRUTHFULNESS_PLUGIN.md).
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
54
|
+
"""Same-device truth check (PLAN_TRUTHFULNESS_PLUGIN.md). The owner socket,
|
|
55
|
+
or an enrolled client the owner lists in TOPOS_TRUTH_CLIENT_ALLOWLIST; any
|
|
56
|
+
bearer on TCP otherwise gets 403 owner_mode_required — the owner key there
|
|
57
|
+
is a third party too. Mirrors the CP door: `app_id` is mandatory and `mode`
|
|
58
|
+
is pinned to fun, so this route cannot reach a mode the registry doesn't
|
|
59
|
+
ship. Body: {"statement": "...", "app_id": "truth-mirror"}."""
|
|
42
60
|
statement = str(body.get("statement") or "").strip()
|
|
43
61
|
app_id = str(body.get("app_id") or "").strip()
|
|
44
62
|
if not statement or not app_id:
|
|
@@ -57,10 +75,10 @@ async def local_verify_claim(
|
|
|
57
75
|
@router.post("/truth_prompts")
|
|
58
76
|
async def local_truth_prompts(
|
|
59
77
|
body: dict = Body(default_factory=dict),
|
|
60
|
-
principal=Depends(
|
|
78
|
+
principal=Depends(_truth_door("truth_prompts")), # noqa: B008
|
|
61
79
|
) -> dict:
|
|
62
80
|
"""Same-device "ask me" prompt seeds (fun aperture; topics only, no
|
|
63
|
-
stances). Body: {"app_id": "truth-mirror", "limit": 5}."""
|
|
81
|
+
stances). Same door as verify_claim. Body: {"app_id": "truth-mirror", "limit": 5}."""
|
|
64
82
|
app_id = str(body.get("app_id") or "").strip()
|
|
65
83
|
if not app_id:
|
|
66
84
|
return {"status": "error", "error": "app_id required"}
|
|
@@ -79,11 +97,12 @@ async def local_truth_prompts(
|
|
|
79
97
|
@router.post("/truth_seed_fact")
|
|
80
98
|
async def local_truth_seed_fact(
|
|
81
99
|
body: dict = Body(default_factory=dict),
|
|
82
|
-
principal=Depends(
|
|
100
|
+
principal=Depends(_truth_door("truth_seed_fact")), # noqa: B008
|
|
83
101
|
) -> dict:
|
|
84
102
|
"""Owner adds a fun fact to their own sheet (refused outside the fun
|
|
85
|
-
aperture).
|
|
86
|
-
|
|
103
|
+
aperture). Owner socket only: the fact is stored as owner-stated, so no
|
|
104
|
+
enrolled client and no bearer on TCP may author it. Body:
|
|
105
|
+
{"predicate": "favorite_food", "value": "tacos", "app_id": "truth-mirror"}."""
|
|
87
106
|
app_id = str(body.get("app_id") or "").strip()
|
|
88
107
|
if not app_id:
|
|
89
108
|
return {"status": "error", "error": "app_id required"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Owner socket access to the same signed identity command as the CP relay."""
|
|
2
|
+
from fastapi import APIRouter, Depends, HTTPException, Request
|
|
3
|
+
from fastapi.responses import JSONResponse
|
|
4
|
+
|
|
5
|
+
from topos.auth import resolve_request_principal
|
|
6
|
+
from topos.permissions_v2.canonical import MAX_BYTES, PolicyError, parse_json
|
|
7
|
+
from topos.permissions_v2.identity_dispatch import execute_signed_identity_command
|
|
8
|
+
|
|
9
|
+
router = APIRouter(prefix="/v1/permissions-beta/v2/identity", tags=["permissions-beta-owner-identity"])
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@router.post("/command")
|
|
13
|
+
async def command(request: Request, principal=Depends(resolve_request_principal)):
|
|
14
|
+
body = bytearray()
|
|
15
|
+
async for chunk in request.stream():
|
|
16
|
+
body.extend(chunk)
|
|
17
|
+
if len(body) > MAX_BYTES:
|
|
18
|
+
raise HTTPException(400, "identity_payload_invalid")
|
|
19
|
+
try:
|
|
20
|
+
payload = parse_json(bytes(body))
|
|
21
|
+
if not isinstance(payload, dict) or set(payload) != {"envelope"}:
|
|
22
|
+
raise PolicyError("identity_payload_invalid")
|
|
23
|
+
ack = await execute_signed_identity_command(payload["envelope"], principal=principal)
|
|
24
|
+
return JSONResponse({"ack": ack.model_dump()}, headers={"Cache-Control": "no-store"})
|
|
25
|
+
except PolicyError as exc:
|
|
26
|
+
code = 404 if exc.code in {"permissions_v2_disabled", "identity_attestations_disabled"} else 403
|
|
27
|
+
raise HTTPException(code, "identity_disabled" if code == 404 else "identity_authority_invalid",
|
|
28
|
+
headers={"Cache-Control": "no-store"}) from None
|
|
29
|
+
except Exception:
|
|
30
|
+
raise HTTPException(503, "identity_unavailable", headers={"Cache-Control": "no-store"}) from None
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Owner socket access to the same signed beta command as the CP relay."""
|
|
2
|
+
from fastapi import APIRouter, Depends, HTTPException, Request
|
|
3
|
+
from fastapi.responses import JSONResponse
|
|
4
|
+
|
|
5
|
+
from topos.auth import resolve_request_principal
|
|
6
|
+
from topos.permissions_v2.canonical import MAX_BYTES, PolicyError, parse_json
|
|
7
|
+
from topos.permissions_v2.ingest_dispatch import execute_signed_ingest
|
|
8
|
+
|
|
9
|
+
router = APIRouter(prefix="/v1/permissions-beta/v2/ingestion", tags=["permissions-beta-owner-ingestion"])
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@router.post("/command")
|
|
13
|
+
async def command(request: Request, principal=Depends(resolve_request_principal)):
|
|
14
|
+
body = bytearray()
|
|
15
|
+
async for chunk in request.stream():
|
|
16
|
+
body.extend(chunk)
|
|
17
|
+
if len(body) > MAX_BYTES:
|
|
18
|
+
raise HTTPException(400, "ingest_payload_invalid")
|
|
19
|
+
try:
|
|
20
|
+
payload = parse_json(bytes(body))
|
|
21
|
+
if not isinstance(payload, dict) or set(payload) != {"envelope"}:
|
|
22
|
+
raise PolicyError("ingest_payload_invalid")
|
|
23
|
+
ack = await execute_signed_ingest(payload["envelope"], principal=principal)
|
|
24
|
+
return JSONResponse({"ack": ack.model_dump()}, headers={"Cache-Control": "no-store"})
|
|
25
|
+
except PolicyError as exc:
|
|
26
|
+
code = 404 if exc.code in {"permissions_v2_disabled", "ingest_snapshots_disabled"} else 403
|
|
27
|
+
raise HTTPException(code, "ingest_disabled" if code == 404 else "ingest_authority_invalid",
|
|
28
|
+
headers={"Cache-Control": "no-store"}) from None
|
|
29
|
+
except Exception:
|
|
30
|
+
raise HTTPException(503, "ingest_unavailable", headers={"Cache-Control": "no-store"}) from None
|