diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..201329c --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,24 @@ +{ + "hooks": { + "PreToolUse": [ + { + "matcher": "Bash|Grep", + "hooks": [ + { + "type": "command", + "command": "command -v graphify >/dev/null 2>&1 || exit 0; graphify hook-guard search" + } + ] + }, + { + "matcher": "Read|Glob", + "hooks": [ + { + "type": "command", + "command": "command -v graphify >/dev/null 2>&1 || exit 0; graphify hook-guard read" + } + ] + } + ] + } +} diff --git a/.gitignore b/.gitignore index c61c968..81ee4e2 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,13 @@ _build/ __pycache__/ *.pyc *.zip + +# graphify knowledge graph. Generated artifacts are not committed, but the +# semantic extraction cache IS: it is the expensive LLM output, and committing +# it lets a teammate rebuild the whole graph with no API key. Listing +# graphify-out/* rather than graphify-out/ is required — git will not descend +# into an ignored directory, which would make the !negations unreachable. +graphify-out/* +!graphify-out/cache/ +graphify-out/cache/* +!graphify-out/cache/semantic/ diff --git a/.graphifyignore b/.graphifyignore new file mode 100644 index 0000000..ec58bbc --- /dev/null +++ b/.graphifyignore @@ -0,0 +1,22 @@ +# graphify scan scope. Composes after .gitignore (which is read first); this +# file can only exclude further, never re-include a path .gitignore dropped. + +# Generated graph artifacts. +graphify-out/ + +# Images cost one vision LLM call each and are UI chrome, not architecture. +*.png +*.jpg +*.jpeg +*.gif +*.svg +*.webp +*.ico + +# Build output, dependency trees and virtualenvs. +dist/ +build/ +.next/ +coverage/ +.venv/ +venv/ diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..417efeb --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,9 @@ +## graphify + +This project has a knowledge graph at graphify-out/ with god nodes, community structure, and cross-file relationships. + +Rules: +- For codebase questions, first run `graphify query ""` when graphify-out/graph.json exists. Use `graphify path "" ""` for relationships and `graphify explain ""` for focused concepts. These return a scoped subgraph, usually much smaller than GRAPH_REPORT.md or raw grep output. +- If graphify-out/wiki/index.md exists, use it for broad navigation instead of raw source browsing. +- Read graphify-out/GRAPH_REPORT.md only for broad architecture review or when query/path/explain do not surface enough context. +- After modifying code, run `graphify update .` to keep the graph current (AST-only, no API cost). diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/003dc80c93edc48773a3a7dff195bc0daea331a84ca77fd8504d30ea4c341987.json b/graphify-out/cache/semantic/pd5fd89c46bb5/003dc80c93edc48773a3a7dff195bc0daea331a84ca77fd8504d30ea4c341987.json new file mode 100644 index 0000000..e683714 --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/003dc80c93edc48773a3a7dff195bc0daea331a84ca77fd8504d30ea4c341987.json @@ -0,0 +1 @@ +{"nodes": [{"id": "_github_workflows_publish_pypi_pypi_publish", "label": "pypi-publish job (Publish to PyPI)", "file_type": "code", "source_file": ".github/workflows/publish-pypi.yaml", "source_location": "lines 8-27", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Release-triggered build with uv and trusted publishing via OIDC (id-token: write) so no long-lived PyPI token is stored in the repo."}], "edges": [{"source": "_github_workflows_publish_pypi_pypi_publish", "target": "_readthedocs_build", "relation": "semantically_similar_to", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": ".github/workflows/publish-pypi.yaml", "source_location": "lines 20-27", "weight": 1.0}, {"source": "_github_workflows_publish_pypi_pypi_publish", "target": "changelog_0_2_4", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": ".github/workflows/publish-pypi.yaml", "source_location": "lines 3-5", "weight": 1.0}], "hyperedges": []} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/2c3975e64208e411f4cb9d411b06c810e513edf1684d1e6cbbe5e998e7ec8c3b.json b/graphify-out/cache/semantic/pd5fd89c46bb5/2c3975e64208e411f4cb9d411b06c810e513edf1684d1e6cbbe5e998e7ec8c3b.json new file mode 100644 index 0000000..05b55b0 --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/2c3975e64208e411f4cb9d411b06c810e513edf1684d1e6cbbe5e998e7ec8c3b.json @@ -0,0 +1 @@ +{"nodes": [{"id": "readme_cm_proxy", "label": "cm-proxy (serverless localhost proxy)", "file_type": "concept", "source_file": "README.rst", "source_location": "lines 1-21", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Built as a cheap, pay-as-you-go AWS serverless replacement for ngrok/localtunnel so engineers can receive third-party webhooks on a local dev server without exposing localhost to the public internet and without paying for a commercial tunnel subscription."}, {"id": "readme_non_goals", "label": "cm-proxy Non-goals", "file_type": "rationale", "source_file": "README.rst", "source_location": "lines 33-39", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Explicitly out of scope: high performance, non-http protocols, streaming responses, non-utf8 responses. Scope is deliberately narrow to keep the codebase small enough to be audited by users who must trust it with AWS credentials."}, {"id": "readme_localhost_not_exposed", "label": "localhost is not publicly exposed", "file_type": "rationale", "source_file": "README.rst", "source_location": "line 28", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "The local machine only ever polls outbound for queued messages, so no inbound port is opened on the dev host. This is the core security property that motivated the queue-based design over a tunnel."}], "edges": [{"source": "readme_cm_proxy", "target": "docs_security_least_privilege", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "README.rst", "source_location": "lines 47,69", "weight": 1.0}, {"source": "readme_cm_proxy", "target": "readme_localhost_not_exposed", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "README.rst", "source_location": "line 28", "weight": 1.0}, {"source": "readme_non_goals", "target": "readme_cm_proxy", "relation": "rationale_for", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "README.rst", "source_location": "lines 33-39", "weight": 1.0}], "hyperedges": [{"id": "cm_proxy_design_tradeoffs", "label": "Design trade-offs justifying the serverless queue architecture", "nodes": ["readme_non_goals", "readme_localhost_not_exposed", "docs_cost_cost_estimate", "docs_security_review_the_code", "docs_how_it_works_unidirectional_proxy", "docs_how_it_works_bidirectional_proxy"], "relation": "form", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "README.rst"}]} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/2e7d8d55195f716c031c5bbb60606ac177ef389b07ebc5eea79c87e305c60944.json b/graphify-out/cache/semantic/pd5fd89c46bb5/2e7d8d55195f716c031c5bbb60606ac177ef389b07ebc5eea79c87e305c60944.json new file mode 100644 index 0000000..1409f90 --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/2e7d8d55195f716c031c5bbb60606ac177ef389b07ebc5eea79c87e305c60944.json @@ -0,0 +1 @@ +{"nodes": [{"id": "cm_proxy_unidirectional_proxy_cmproxyfunction", "label": "CMProxyFunction (unidirectional lambda)", "file_type": "code", "source_file": "cm_proxy/unidirectional-proxy.yaml", "source_location": "lines 62-82", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Inline python3.14 arm64 lambda that only sends the event to SQS and immediately returns a fixed 200 body, keeping cost and latency minimal."}, {"id": "cm_proxy_unidirectional_proxy_handler", "label": "handler (unidirectional inline lambda handler)", "file_type": "code", "source_file": "cm_proxy/unidirectional-proxy.yaml", "source_location": "lines 71-76", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "cm_proxy_unidirectional_proxy_cmproxyrequestqueue", "label": "CMProxyRequestQueue (unidirectional)", "file_type": "code", "source_file": "cm_proxy/unidirectional-proxy.yaml", "source_location": "lines 43-44", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "cm_proxy_unidirectional_proxy_lambdarole", "label": "LambdaRole (unidirectional)", "file_type": "code", "source_file": "cm_proxy/unidirectional-proxy.yaml", "source_location": "lines 14-41", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "cm_proxy_unidirectional_proxy_cmproxyurl", "label": "CMProxyUrl (unidirectional Function URL)", "file_type": "code", "source_file": "cm_proxy/unidirectional-proxy.yaml", "source_location": "lines 84-88", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "cm_proxy_unidirectional_proxy_permissionsboundary", "label": "PermissionsBoundary parameter (unidirectional)", "file_type": "code", "source_file": "cm_proxy/unidirectional-proxy.yaml", "source_location": "lines 4-10", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Optional template parameter; the HavePermissionsBoundary condition compares against the literal string \"null\" so the same template works with and without least-privilege deployment."}], "edges": [{"source": "cm_proxy_unidirectional_proxy_cmproxyfunction", "target": "docs_how_it_works_unidirectional_proxy", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "cm_proxy/unidirectional-proxy.yaml", "source_location": "lines 62-82", "weight": 1.0}, {"source": "cm_proxy_unidirectional_proxy_handler", "target": "cm_proxy_unidirectional_proxy_cmproxyrequestqueue", "relation": "shares_data_with", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "cm_proxy/unidirectional-proxy.yaml", "source_location": "lines 71-76", "weight": 1.0}, {"source": "cm_proxy_unidirectional_proxy_cmproxyurl", "target": "cm_proxy_unidirectional_proxy_cmproxyfunction", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "cm_proxy/unidirectional-proxy.yaml", "source_location": "lines 84-88", "weight": 1.0}, {"source": "cm_proxy_unidirectional_proxy_cmproxyfunction", "target": "cm_proxy_unidirectional_proxy_lambdarole", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "cm_proxy/unidirectional-proxy.yaml", "source_location": "line 82", "weight": 1.0}, {"source": "cm_proxy_unidirectional_proxy_lambdarole", "target": "cm_proxy_unidirectional_proxy_cmproxyrequestqueue", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "cm_proxy/unidirectional-proxy.yaml", "source_location": "lines 32-41", "weight": 1.0}, {"source": "cm_proxy_unidirectional_proxy_lambdarole", "target": "cm_proxy_unidirectional_proxy_permissionsboundary", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "cm_proxy/unidirectional-proxy.yaml", "source_location": "lines 25-28", "weight": 1.0}, {"source": "cm_proxy_unidirectional_proxy_handler", "target": "cm_proxy_bidirectional_proxy_handler", "relation": "semantically_similar_to", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "cm_proxy/unidirectional-proxy.yaml", "source_location": "lines 71-76", "weight": 1.0}, {"source": "cm_proxy_unidirectional_proxy_cmproxyrequestqueue", "target": "cm_proxy_bidirectional_proxy_cmproxyrequestqueue", "relation": "semantically_similar_to", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "cm_proxy/unidirectional-proxy.yaml", "source_location": "lines 43-44", "weight": 1.0}], "hyperedges": []} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/3bb842eeffc09a2ac8699d7852ed495c5eca4327c3cc51cb9bd2abd780570675.json b/graphify-out/cache/semantic/pd5fd89c46bb5/3bb842eeffc09a2ac8699d7852ed495c5eca4327c3cc51cb9bd2abd780570675.json new file mode 100644 index 0000000..bc78dfc --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/3bb842eeffc09a2ac8699d7852ed495c5eca4327c3cc51cb9bd2abd780570675.json @@ -0,0 +1 @@ +{"nodes": [{"id": "docs_use_autoprogram", "label": "CLI reference via sphinx autoprogram", "file_type": "document", "source_file": "docs/use.rst", "source_location": "line 4", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "The usage page is generated directly from cm_proxy.proxy:get_parser() so CLI docs cannot drift from the argparse definition."}], "edges": [{"source": "docs_use_autoprogram", "target": "cm_proxy_proxy_get_parser", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/use.rst", "source_location": "line 4", "weight": 1.0}], "hyperedges": []} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/3c5ff577910d12c155011086b94333968827da53098281986812f052591607c1.json b/graphify-out/cache/semantic/pd5fd89c46bb5/3c5ff577910d12c155011086b94333968827da53098281986812f052591607c1.json new file mode 100644 index 0000000..45c2416 --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/3c5ff577910d12c155011086b94333968827da53098281986812f052591607c1.json @@ -0,0 +1 @@ +{"nodes": [{"id": "docs_images_bidirectional_proxy_diagram", "label": "Bidirectional Proxy Architecture Diagram", "file_type": "image", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_aws", "label": "AWS (cloud boundary)", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_local_dev_host", "label": "Local Dev Host (boundary)", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_incoming_request", "label": "Incoming Request", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_lambda", "label": "Lambda", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_state_machine", "label": "State Machine (Step Functions)", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_request_queue", "label": "Request Queue", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_cm_proxy", "label": "cm-proxy", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_mitmproxy", "label": "mitmproxy", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_local_server", "label": "local server", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_startexecution", "label": "StartExecution", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_describeexecution_poll", "label": "DescribeExecution (Poll)", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_receivemessage", "label": "ReceiveMessage", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_sendtasksuccess", "label": "SendTaskSuccess", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_http", "label": "http (plain HTTP hop)", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_bidirectional_tunnel", "label": "Bidirectional Proxy Tunnel (pull-based inbound delivery)", "file_type": "rationale", "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "The diagram shows the local dev host never being connected to inbound from AWS. Instead cm-proxy on the local host pulls work (ReceiveMessage from the Request Queue) and pushes the result back (SendTaskSuccess to the State Machine), while the Lambda holds the caller's connection open by polling DescribeExecution. This inverts the direction of initiation so a machine behind NAT/firewall with no public address can serve real inbound AWS traffic, at the cost of poll latency and Step Functions task-token bookkeeping."}], "edges": [{"source": "docs_images_bidirectional_proxy_diagram", "target": "docs_images_bidirectional_proxy_aws", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_diagram", "target": "docs_images_bidirectional_proxy_local_dev_host", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_aws", "target": "docs_images_bidirectional_proxy_lambda", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_aws", "target": "docs_images_bidirectional_proxy_state_machine", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_aws", "target": "docs_images_bidirectional_proxy_request_queue", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_local_dev_host", "target": "docs_images_bidirectional_proxy_cm_proxy", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_local_dev_host", "target": "docs_images_bidirectional_proxy_mitmproxy", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_local_dev_host", "target": "docs_images_bidirectional_proxy_local_server", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_incoming_request", "target": "docs_images_bidirectional_proxy_lambda", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_lambda", "target": "docs_images_bidirectional_proxy_startexecution", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_startexecution", "target": "docs_images_bidirectional_proxy_state_machine", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_lambda", "target": "docs_images_bidirectional_proxy_describeexecution_poll", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_describeexecution_poll", "target": "docs_images_bidirectional_proxy_state_machine", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_lambda", "target": "docs_images_bidirectional_proxy_state_machine", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_state_machine", "target": "docs_images_bidirectional_proxy_request_queue", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_cm_proxy", "target": "docs_images_bidirectional_proxy_receivemessage", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_receivemessage", "target": "docs_images_bidirectional_proxy_request_queue", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_cm_proxy", "target": "docs_images_bidirectional_proxy_request_queue", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_cm_proxy", "target": "docs_images_bidirectional_proxy_sendtasksuccess", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_sendtasksuccess", "target": "docs_images_bidirectional_proxy_state_machine", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_cm_proxy", "target": "docs_images_bidirectional_proxy_state_machine", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_cm_proxy", "target": "docs_images_bidirectional_proxy_mitmproxy", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_mitmproxy", "target": "docs_images_bidirectional_proxy_cm_proxy", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_mitmproxy", "target": "docs_images_bidirectional_proxy_local_server", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_local_server", "target": "docs_images_bidirectional_proxy_mitmproxy", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_http", "target": "docs_images_bidirectional_proxy_local_server", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_http", "target": "docs_images_bidirectional_proxy_mitmproxy", "relation": "references", "confidence": "AMBIGUOUS", "confidence_score": 0.3, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_bidirectional_tunnel", "target": "docs_images_bidirectional_proxy_cm_proxy", "relation": "rationale_for", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_bidirectional_tunnel", "target": "docs_images_bidirectional_proxy_request_queue", "relation": "rationale_for", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_receivemessage", "target": "docs_images_bidirectional_proxy_describeexecution_poll", "relation": "semantically_similar_to", "confidence": "INFERRED", "confidence_score": 0.8, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_sendtasksuccess", "target": "docs_images_bidirectional_proxy_startexecution", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_mitmproxy", "target": "docs_images_bidirectional_proxy_bidirectional_tunnel", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "docs/images/bidirectional-proxy.svg", "source_location": null, "weight": 1.0}], "hyperedges": [{"id": "inbound_request_path", "label": "Inbound request path: caller to AWS to local host", "nodes": ["docs_images_bidirectional_proxy_incoming_request", "docs_images_bidirectional_proxy_lambda", "docs_images_bidirectional_proxy_state_machine", "docs_images_bidirectional_proxy_request_queue", "docs_images_bidirectional_proxy_cm_proxy"], "relation": "participate_in", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg"}, {"id": "local_delivery_loop", "label": "Local delivery loop on the dev host over plain http", "nodes": ["docs_images_bidirectional_proxy_cm_proxy", "docs_images_bidirectional_proxy_mitmproxy", "docs_images_bidirectional_proxy_local_server", "docs_images_bidirectional_proxy_http"], "relation": "participate_in", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.svg"}, {"id": "response_completion_handshake", "label": "Response completion handshake via task token and Lambda polling", "nodes": ["docs_images_bidirectional_proxy_cm_proxy", "docs_images_bidirectional_proxy_sendtasksuccess", "docs_images_bidirectional_proxy_state_machine", "docs_images_bidirectional_proxy_describeexecution_poll", "docs_images_bidirectional_proxy_lambda"], "relation": "form", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/images/bidirectional-proxy.svg"}]} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/44598b03ef941e21ee40c0b3828344b1643c94902121057e1740bceee781143a.json b/graphify-out/cache/semantic/pd5fd89c46bb5/44598b03ef941e21ee40c0b3828344b1643c94902121057e1740bceee781143a.json new file mode 100644 index 0000000..84e79da --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/44598b03ef941e21ee40c0b3828344b1643c94902121057e1740bceee781143a.json @@ -0,0 +1 @@ +{"nodes": [{"id": "docs_images_bidirectional_proxy_diagram", "label": "Bidirectional Proxy Architecture Diagram", "file_type": "image", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_aws_boundary", "label": "AWS Cloud Boundary", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_local_dev_host", "label": "Local Dev Host Boundary", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_incoming_request", "label": "Incoming Request", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_lambda", "label": "Lambda (Proxy Entry Point)", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_state_machine", "label": "Step Functions State Machine", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_request_queue", "label": "Request Queue (SQS)", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_cm_proxy", "label": "cm-proxy (Local Agent)", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_mitmproxy", "label": "mitmproxy (Local Interceptor)", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_local_server", "label": "Local HTTP Server", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_startexecution", "label": "StartExecution Call", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_describeexecution_poll", "label": "DescribeExecution Polling", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_sendtasksuccess", "label": "SendTaskSuccess Callback", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_receivemessage", "label": "ReceiveMessage Long Poll", "file_type": "concept", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_bidirectional_proxy_bidirectional_tunnel_pattern", "label": "Bidirectional Cloud-to-Localhost Tunnel Pattern", "file_type": "rationale", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "The diagram shows no inbound connection from AWS into the Local Dev Host: the local agent always initiates outbound calls (ReceiveMessage to pull work, SendTaskSuccess to return the result). This lets a cloud-hosted request reach a developer's machine behind NAT/firewall without any inbound port, tunnel service, or public hostname."}, {"id": "docs_images_bidirectional_proxy_wait_for_task_token", "label": "Wait-for-Task-Token Suspension", "file_type": "rationale", "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "The State Machine parks the execution after enqueueing to the Request Queue and only resumes when SendTaskSuccess arrives from the local host, so the long, unbounded wait for a human-operated dev machine is held in Step Functions rather than in billed Lambda execution time. The Lambda instead cheaply polls DescribeExecution for the outcome."}], "edges": [{"source": "docs_images_bidirectional_proxy_diagram", "target": "docs_images_bidirectional_proxy_aws_boundary", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_diagram", "target": "docs_images_bidirectional_proxy_local_dev_host", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_aws_boundary", "target": "docs_images_bidirectional_proxy_lambda", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_aws_boundary", "target": "docs_images_bidirectional_proxy_state_machine", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_aws_boundary", "target": "docs_images_bidirectional_proxy_request_queue", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_local_dev_host", "target": "docs_images_bidirectional_proxy_cm_proxy", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_local_dev_host", "target": "docs_images_bidirectional_proxy_mitmproxy", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_local_dev_host", "target": "docs_images_bidirectional_proxy_local_server", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_incoming_request", "target": "docs_images_bidirectional_proxy_lambda", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_lambda", "target": "docs_images_bidirectional_proxy_startexecution", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_startexecution", "target": "docs_images_bidirectional_proxy_state_machine", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_lambda", "target": "docs_images_bidirectional_proxy_describeexecution_poll", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_describeexecution_poll", "target": "docs_images_bidirectional_proxy_state_machine", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_state_machine", "target": "docs_images_bidirectional_proxy_request_queue", "relation": "shares_data_with", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_cm_proxy", "target": "docs_images_bidirectional_proxy_receivemessage", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_receivemessage", "target": "docs_images_bidirectional_proxy_request_queue", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_cm_proxy", "target": "docs_images_bidirectional_proxy_sendtasksuccess", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_sendtasksuccess", "target": "docs_images_bidirectional_proxy_state_machine", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_cm_proxy", "target": "docs_images_bidirectional_proxy_mitmproxy", "relation": "shares_data_with", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_mitmproxy", "target": "docs_images_bidirectional_proxy_local_server", "relation": "shares_data_with", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_bidirectional_tunnel_pattern", "target": "docs_images_bidirectional_proxy_cm_proxy", "relation": "rationale_for", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_wait_for_task_token", "target": "docs_images_bidirectional_proxy_state_machine", "relation": "rationale_for", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_wait_for_task_token", "target": "docs_images_bidirectional_proxy_sendtasksuccess", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_bidirectional_tunnel_pattern", "target": "docs_images_bidirectional_proxy_receivemessage", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_describeexecution_poll", "target": "docs_images_bidirectional_proxy_receivemessage", "relation": "semantically_similar_to", "confidence": "INFERRED", "confidence_score": 0.8, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_bidirectional_proxy_mitmproxy", "target": "docs_images_bidirectional_proxy_lambda", "relation": "semantically_similar_to", "confidence": "INFERRED", "confidence_score": 0.65, "source_file": "docs/images/bidirectional-proxy.png", "source_location": null, "weight": 1.0}], "hyperedges": [{"id": "cloud_to_local_request_round_trip", "label": "Cloud-to-Local Request Round Trip", "nodes": ["docs_images_bidirectional_proxy_lambda", "docs_images_bidirectional_proxy_state_machine", "docs_images_bidirectional_proxy_request_queue", "docs_images_bidirectional_proxy_cm_proxy", "docs_images_bidirectional_proxy_mitmproxy", "docs_images_bidirectional_proxy_local_server"], "relation": "participate_in", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/bidirectional-proxy.png"}, {"id": "outbound_only_local_polling_loop", "label": "Outbound-Only Local Polling and Callback Loop", "nodes": ["docs_images_bidirectional_proxy_cm_proxy", "docs_images_bidirectional_proxy_receivemessage", "docs_images_bidirectional_proxy_sendtasksuccess", "docs_images_bidirectional_proxy_bidirectional_tunnel_pattern"], "relation": "form", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/images/bidirectional-proxy.png"}]} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/4b57e8919332b78094009d6d2aa7a175b2f6f50f4dde1fb8c3a30069a71ae668.json b/graphify-out/cache/semantic/pd5fd89c46bb5/4b57e8919332b78094009d6d2aa7a175b2f6f50f4dde1fb8c3a30069a71ae668.json new file mode 100644 index 0000000..cafcab5 --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/4b57e8919332b78094009d6d2aa7a175b2f6f50f4dde1fb8c3a30069a71ae668.json @@ -0,0 +1 @@ +{"nodes": [{"id": "authors_aryeh_leib_taurog", "label": "Aryeh Leib Taurog (@altaurog)", "file_type": "document", "source_file": "AUTHORS.rst", "source_location": "line 4", "source_url": "https://github.com/altaurog", "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "authors_aryeh_leib_taurog", "target": "readme_cm_proxy", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "AUTHORS.rst", "source_location": "line 4", "weight": 1.0}], "hyperedges": []} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/4fcfd81a565a956235aec5d822b762fd2499de206d71e66b7d844b1d6178e03c.json b/graphify-out/cache/semantic/pd5fd89c46bb5/4fcfd81a565a956235aec5d822b762fd2499de206d71e66b7d844b1d6178e03c.json new file mode 100644 index 0000000..2398d18 --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/4fcfd81a565a956235aec5d822b762fd2499de206d71e66b7d844b1d6178e03c.json @@ -0,0 +1 @@ +{"nodes": [], "edges": [{"source": "docs_index_toctree", "target": "authors_aryeh_leib_taurog", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/authors.rst", "source_location": "line 1", "weight": 1.0}], "hyperedges": []} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/548ffc43cf4a7526f4aeeecf93e67b326d698936cf36dd049ce79e051904034c.json b/graphify-out/cache/semantic/pd5fd89c46bb5/548ffc43cf4a7526f4aeeecf93e67b326d698936cf36dd049ce79e051904034c.json new file mode 100644 index 0000000..136d2c8 --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/548ffc43cf4a7526f4aeeecf93e67b326d698936cf36dd049ce79e051904034c.json @@ -0,0 +1 @@ +{"nodes": [{"id": "docs_security_review_the_code", "label": "Review the Code (auditability)", "file_type": "rationale", "source_file": "docs/security.rst", "source_location": "lines 9-13", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "cm-proxy is kept intentionally simple so that a user can fully code-audit it before trusting it with AWS credentials; simplicity is treated as a security feature, not just a style preference."}, {"id": "docs_security_non_production_account", "label": "Use a non-production AWS account", "file_type": "rationale", "source_file": "docs/security.rst", "source_location": "lines 15-19", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Running in a sandbox or dedicated AWS Organizations account isolates third-party code from production secrets, a blast-radius control that is cheap to set up."}, {"id": "docs_security_least_privilege", "label": "Principle of Least Privilege", "file_type": "rationale", "source_file": "docs/security.rst", "source_location": "lines 21-39", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "An optional extra CloudFormation template (proxy-role.yaml) creates the cm-proxy-policy managed policy with the minimum permissions needed. Accepted trade-off: the tightly scoped ARN patterns restrict cm-proxy to a single AWS region."}], "edges": [{"source": "docs_security_least_privilege", "target": "proxy_role_cmproxypolicy", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/security.rst", "source_location": "lines 28-32", "weight": 1.0}, {"source": "docs_security_least_privilege", "target": "proxy_role_cmproxypermissionsboundary", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "docs/security.rst", "source_location": "lines 21-32", "weight": 1.0}, {"source": "docs_security_review_the_code", "target": "readme_non_goals", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/security.rst", "source_location": "lines 9-13", "weight": 1.0}, {"source": "docs_security_non_production_account", "target": "readme_localhost_not_exposed", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.65, "source_file": "docs/security.rst", "source_location": "lines 15-19", "weight": 1.0}, {"source": "docs_security_non_production_account", "target": "readme_cm_proxy", "relation": "references", "confidence": "AMBIGUOUS", "confidence_score": 0.25, "source_file": "docs/security.rst", "source_location": "line 17", "weight": 1.0}], "hyperedges": []} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/6d253dfd8276a8a2d40ca23e4e56538e3ba68b8b1b883df3bdb13a138e0e979e.json b/graphify-out/cache/semantic/pd5fd89c46bb5/6d253dfd8276a8a2d40ca23e4e56538e3ba68b8b1b883df3bdb13a138e0e979e.json new file mode 100644 index 0000000..93b71d4 --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/6d253dfd8276a8a2d40ca23e4e56538e3ba68b8b1b883df3bdb13a138e0e979e.json @@ -0,0 +1 @@ +{"nodes": [{"id": "_serena_project_config", "label": "Serena project configuration (cm-proxy)", "file_type": "code", "source_file": ".serena/project.yml", "source_location": "lines 1-40", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Declares cm-proxy as a single-language python project for the LSP backend, indexing the whole repo root and honouring .gitignore."}], "edges": [{"source": "_serena_project_config", "target": "readme_cm_proxy", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": ".serena/project.yml", "source_location": "line 2", "weight": 1.0}], "hyperedges": []} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/6e2e64a73a097e1b554c80ea2784252651d7663d82b385296fd3e3395301e4c6.json b/graphify-out/cache/semantic/pd5fd89c46bb5/6e2e64a73a097e1b554c80ea2784252651d7663d82b385296fd3e3395301e4c6.json new file mode 100644 index 0000000..1463f65 --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/6e2e64a73a097e1b554c80ea2784252651d7663d82b385296fd3e3395301e4c6.json @@ -0,0 +1 @@ +{"nodes": [{"id": "_readthedocs_build", "label": "Read the Docs build configuration", "file_type": "code", "source_file": ".readthedocs.yaml", "source_location": "lines 1-19", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Overrides RTD's default env creation to install uv via asdf and run `uv sync --frozen --group docs`, keeping docs builds on the same locked dependency set as local development."}], "edges": [{"source": "_readthedocs_build", "target": "docs_index_toctree", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": ".readthedocs.yaml", "source_location": "lines 18-19", "weight": 1.0}], "hyperedges": []} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/6ef9463d842dc59e90128c5b94d9004093b4fa9eb73506ae29e360797fb76d7d.json b/graphify-out/cache/semantic/pd5fd89c46bb5/6ef9463d842dc59e90128c5b94d9004093b4fa9eb73506ae29e360797fb76d7d.json new file mode 100644 index 0000000..7b97ac4 --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/6ef9463d842dc59e90128c5b94d9004093b4fa9eb73506ae29e360797fb76d7d.json @@ -0,0 +1 @@ +{"nodes": [{"id": "docs_cost_cost_estimate", "label": "cm-proxy cost estimate", "file_type": "concept", "source_file": "docs/cost.rst", "source_location": "lines 1-19", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "At 2kB request/response: unidirectional $0.0011 per 1000 requests (1M free tier), bidirectional $0.0275 per 1000 requests (4k free tier). Cost is published to justify the build-vs-buy decision against ngrok."}], "edges": [{"source": "docs_cost_cost_estimate", "target": "docs_how_it_works_unidirectional_proxy", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/cost.rst", "source_location": "line 11", "weight": 1.0}, {"source": "docs_cost_cost_estimate", "target": "docs_how_it_works_bidirectional_proxy", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/cost.rst", "source_location": "line 12", "weight": 1.0}, {"source": "docs_cost_cost_estimate", "target": "readme_cm_proxy", "relation": "rationale_for", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/cost.rst", "source_location": "lines 4-6", "weight": 1.0}], "hyperedges": []} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/a1765f733b8ff75c964225964225a07ae37b70443e322597efc54c4143877132.json b/graphify-out/cache/semantic/pd5fd89c46bb5/a1765f733b8ff75c964225964225a07ae37b70443e322597efc54c4143877132.json new file mode 100644 index 0000000..614bf0e --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/a1765f733b8ff75c964225964225a07ae37b70443e322597efc54c4143877132.json @@ -0,0 +1 @@ +{"nodes": [{"id": "docs_how_it_works_unidirectional_proxy", "label": "Unidirectional Proxy mode", "file_type": "concept", "source_file": "docs/how-it-works.rst", "source_location": "lines 11-20", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Default mode. A fixed 200 response is returned as soon as the request is enqueued and the local response is discarded. Chosen as the default because it needs only a lambda plus an SQS queue, is ~25x cheaper, and fits within the 1M-request free tier."}, {"id": "docs_how_it_works_bidirectional_proxy", "label": "Bidirectional Proxy mode", "file_type": "concept", "source_file": "docs/how-it-works.rst", "source_location": "lines 22-33", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "The request handler waits up to 25 seconds for the local response and forwards it back to the requester. Implemented with a lambda, a state machine and a queue: the lambda polls for the response while the Step Functions task token simplifies associating a response with its original request."}, {"id": "docs_how_it_works_task_token_correlation", "label": "Task-token request/response correlation", "file_type": "rationale", "source_file": "docs/how-it-works.rst", "source_location": "lines 31-33", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "A Step Functions state machine with waitForTaskToken is used instead of hand-rolled correlation IDs because it makes matching an inbound local response back to the paused request trivial and durable."}], "edges": [{"source": "docs_how_it_works_unidirectional_proxy", "target": "docs_how_it_works_bidirectional_proxy", "relation": "semantically_similar_to", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/how-it-works.rst", "source_location": "lines 11-33", "weight": 1.0}], "hyperedges": []} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/ac7550e0eb7b2a6f2c1574cdb342a91e3dbd8789d31139fb58c06279c35a0f4b.json b/graphify-out/cache/semantic/pd5fd89c46bb5/ac7550e0eb7b2a6f2c1574cdb342a91e3dbd8789d31139fb58c06279c35a0f4b.json new file mode 100644 index 0000000..fb43a1a --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/ac7550e0eb7b2a6f2c1574cdb342a91e3dbd8789d31139fb58c06279c35a0f4b.json @@ -0,0 +1 @@ +{"nodes": [], "edges": [{"source": "docs_index_toctree", "target": "changelog_0_2_4", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/changelog.rst", "source_location": "line 1", "weight": 1.0}], "hyperedges": []} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/bac3c18396bbf88ab55873efcb71515a0d02291026361526459c2f486c40899c.json b/graphify-out/cache/semantic/pd5fd89c46bb5/bac3c18396bbf88ab55873efcb71515a0d02291026361526459c2f486c40899c.json new file mode 100644 index 0000000..6dd083f --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/bac3c18396bbf88ab55873efcb71515a0d02291026361526459c2f486c40899c.json @@ -0,0 +1 @@ +{"nodes": [{"id": "docs_images_unidirectional_proxy_diagram", "label": "Unidirectional Proxy Architecture Diagram", "file_type": "image", "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_incoming_request", "label": "Incoming Request", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_aws_boundary", "label": "AWS (Cloud Boundary)", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_lambda", "label": "Lambda", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_request_queue", "label": "Request Queue", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_receivemessage", "label": "ReceiveMessage (Queue Poll)", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_local_dev_host", "label": "Local Dev Host (Boundary)", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_cm_proxy", "label": "cm-proxy", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_mitmproxy", "label": "mitmproxy", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_local_server", "label": "Local HTTP Server", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_unidirectional_mode", "label": "Unidirectional (Fire-and-Forget) Mode", "file_type": "rationale", "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "The diagram shows request flow travelling one way only: incoming request enters Lambda, Lambda enqueues to the Request Queue, and cm-proxy on the local dev host pulls work via ReceiveMessage. No arrow returns a response from the local dev host back to AWS or to the original caller, so the cloud side does not wait for a local reply. Only the local leg (cm-proxy <-> mitmproxy <-> local server) is bidirectional, because the local server's response is needed for inspection but is never propagated upstream. This decouples the cloud caller from local availability and latency: Lambda can return immediately after enqueueing, and the local developer environment can be offline or slow without breaking the cloud path. The trade-off is that the caller cannot receive the local server's response, making this mode suitable for webhooks and async side-effect traffic rather than request/response APIs."}, {"id": "docs_images_unidirectional_proxy_queue_pull_pattern", "label": "Queue-Based Pull Tunneling", "file_type": "rationale", "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "The local dev host reaches into AWS with ReceiveMessage rather than AWS pushing inbound connections to the developer machine. Because the connection is initiated outbound from the local side, no public ingress, port forwarding, or tunnel hostname is required, and the queue buffers traffic while the developer is disconnected."}, {"id": "docs_images_unidirectional_proxy_traffic_interception", "label": "Local Traffic Interception Chain", "file_type": "rationale", "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "cm-proxy replays the dequeued request through mitmproxy instead of hitting the local server directly, so the developer gets full request/response inspection and rewriting of cloud-originated traffic in an existing familiar tool rather than cm-proxy reimplementing logging and interception itself."}], "edges": [{"source": "docs_images_unidirectional_proxy_diagram", "target": "docs_images_unidirectional_proxy_aws_boundary", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_diagram", "target": "docs_images_unidirectional_proxy_local_dev_host", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_incoming_request", "target": "docs_images_unidirectional_proxy_lambda", "relation": "shares_data_with", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_lambda", "target": "docs_images_unidirectional_proxy_request_queue", "relation": "shares_data_with", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_lambda", "target": "docs_images_unidirectional_proxy_aws_boundary", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_request_queue", "target": "docs_images_unidirectional_proxy_aws_boundary", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_cm_proxy", "target": "docs_images_unidirectional_proxy_receivemessage", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_receivemessage", "target": "docs_images_unidirectional_proxy_request_queue", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_cm_proxy", "target": "docs_images_unidirectional_proxy_local_dev_host", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_mitmproxy", "target": "docs_images_unidirectional_proxy_local_dev_host", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_local_server", "target": "docs_images_unidirectional_proxy_local_dev_host", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_cm_proxy", "target": "docs_images_unidirectional_proxy_mitmproxy", "relation": "shares_data_with", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_mitmproxy", "target": "docs_images_unidirectional_proxy_local_server", "relation": "shares_data_with", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_unidirectional_mode", "target": "docs_images_unidirectional_proxy_diagram", "relation": "rationale_for", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_queue_pull_pattern", "target": "docs_images_unidirectional_proxy_receivemessage", "relation": "rationale_for", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_traffic_interception", "target": "docs_images_unidirectional_proxy_mitmproxy", "relation": "rationale_for", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_unidirectional_mode", "target": "docs_images_unidirectional_proxy_request_queue", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_queue_pull_pattern", "target": "docs_images_unidirectional_proxy_unidirectional_mode", "relation": "semantically_similar_to", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "docs/images/unidirectional-proxy.png", "source_location": null, "weight": 1.0}], "hyperedges": [{"id": "unidirectional_request_delivery_flow", "label": "Unidirectional Request Delivery Flow (cloud to local)", "nodes": ["docs_images_unidirectional_proxy_incoming_request", "docs_images_unidirectional_proxy_lambda", "docs_images_unidirectional_proxy_request_queue", "docs_images_unidirectional_proxy_receivemessage", "docs_images_unidirectional_proxy_cm_proxy"], "relation": "participate_in", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png"}, {"id": "local_interception_chain", "label": "Local Bidirectional Interception Chain", "nodes": ["docs_images_unidirectional_proxy_cm_proxy", "docs_images_unidirectional_proxy_mitmproxy", "docs_images_unidirectional_proxy_local_server", "docs_images_unidirectional_proxy_traffic_interception"], "relation": "form", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.png"}]} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/c30558c7af11d434f93ceb2fec819a48d4c376d77c12ffaa816bd317f0882402.json b/graphify-out/cache/semantic/pd5fd89c46bb5/c30558c7af11d434f93ceb2fec819a48d4c376d77c12ffaa816bd317f0882402.json new file mode 100644 index 0000000..29db6df --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/c30558c7af11d434f93ceb2fec819a48d4c376d77c12ffaa816bd317f0882402.json @@ -0,0 +1 @@ +{"nodes": [{"id": "docs_index_toctree", "label": "Documentation table of contents", "file_type": "document", "source_file": "docs/index.rst", "source_location": "lines 10-21", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "docs_index_toctree", "target": "docs_use_autoprogram", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/index.rst", "source_location": "line 14", "weight": 1.0}, {"source": "docs_index_toctree", "target": "docs_how_it_works_unidirectional_proxy", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/index.rst", "source_location": "line 15", "weight": 1.0}, {"source": "docs_index_toctree", "target": "docs_how_it_works_bidirectional_proxy", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/index.rst", "source_location": "line 15", "weight": 1.0}, {"source": "docs_index_toctree", "target": "docs_security_least_privilege", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/index.rst", "source_location": "line 16", "weight": 1.0}, {"source": "docs_index_toctree", "target": "docs_cost_cost_estimate", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/index.rst", "source_location": "line 17", "weight": 1.0}, {"source": "docs_index_toctree", "target": "readme_cm_proxy", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/index.rst", "source_location": "lines 4-6", "weight": 1.0}], "hyperedges": []} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/ceaf6c49d7ae6dfb280e96ab77b28b555681f3ca9929c6e4a3cf4d24e6c0ef55.json b/graphify-out/cache/semantic/pd5fd89c46bb5/ceaf6c49d7ae6dfb280e96ab77b28b555681f3ca9929c6e4a3cf4d24e6c0ef55.json new file mode 100644 index 0000000..c8794d4 --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/ceaf6c49d7ae6dfb280e96ab77b28b555681f3ca9929c6e4a3cf4d24e6c0ef55.json @@ -0,0 +1 @@ +{"nodes": [], "edges": [{"source": "docs_index_toctree", "target": "license_mit_causematch_israel", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/license.rst", "source_location": "line 1", "weight": 1.0}], "hyperedges": []} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/e2d814813da3b1b511b9ea4654f38e73a8d119571ce9972b81e5010f913e40e5.json b/graphify-out/cache/semantic/pd5fd89c46bb5/e2d814813da3b1b511b9ea4654f38e73a8d119571ce9972b81e5010f913e40e5.json new file mode 100644 index 0000000..c1532d2 --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/e2d814813da3b1b511b9ea4654f38e73a8d119571ce9972b81e5010f913e40e5.json @@ -0,0 +1 @@ +{"nodes": [{"id": "license_mit_causematch_israel", "label": "MIT License, CauseMatch Israel 2025-2026", "file_type": "document", "source_file": "LICENSE.txt", "source_location": "lines 1-15", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "license_mit_causematch_israel", "target": "readme_cm_proxy", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "LICENSE.txt", "source_location": "line 4", "weight": 1.0}], "hyperedges": []} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/ead283db71be483b5348fced603a9708473b18ac08833fe8476f24063b493c9a.json b/graphify-out/cache/semantic/pd5fd89c46bb5/ead283db71be483b5348fced603a9708473b18ac08833fe8476f24063b493c9a.json new file mode 100644 index 0000000..3556a59 --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/ead283db71be483b5348fced603a9708473b18ac08833fe8476f24063b493c9a.json @@ -0,0 +1 @@ +{"nodes": [{"id": "cm_proxy_bidirectional_proxy_cmproxyfunction", "label": "CMProxyFunction (bidirectional lambda)", "file_type": "code", "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 110-137", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Inline python3.14 arm64 lambda that starts a Step Functions execution then polls describe_execution 100 times at 0.25s intervals (~25s) before returning a 503 timeout; polling is used because Function URLs are synchronous and cannot wait on an async callback."}, {"id": "cm_proxy_bidirectional_proxy_handler", "label": "handler (bidirectional inline lambda handler)", "file_type": "code", "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 120-131", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "cm_proxy_bidirectional_proxy_cmproxystatemachine", "label": "CMProxyStateMachine", "file_type": "code", "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 92-108", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "JSONata-language state machine with a single EnqueueRequest task using sqs:sendMessage.waitForTaskToken, so the execution stays paused until the local side calls SendTaskSuccess with the response."}, {"id": "cm_proxy_bidirectional_proxy_enqueuerequest", "label": "EnqueueRequest state", "file_type": "code", "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 100-108", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "cm_proxy_bidirectional_proxy_cmproxyrequestqueue", "label": "CMProxyRequestQueue (bidirectional)", "file_type": "code", "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 89-90", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "cm_proxy_bidirectional_proxy_statemachinerole", "label": "StateMachineRole", "file_type": "code", "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 15-40", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "cm_proxy_bidirectional_proxy_lambdarole", "label": "LambdaRole (bidirectional)", "file_type": "code", "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 42-71", "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "cm_proxy_bidirectional_proxy_cmproxyurl", "label": "CMProxyUrl (bidirectional Function URL)", "file_type": "code", "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 139-148", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "AuthType NONE public https endpoint; unauthenticated by design because third-party webhook senders cannot sign with SigV4."}, {"id": "cm_proxy_bidirectional_proxy_permissionsboundary", "label": "PermissionsBoundary parameter (bidirectional)", "file_type": "code", "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 5-11", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "cm_proxy_bidirectional_proxy_cmproxyfunction", "target": "docs_how_it_works_bidirectional_proxy", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 110-137", "weight": 1.0}, {"source": "cm_proxy_bidirectional_proxy_cmproxystatemachine", "target": "docs_how_it_works_task_token_correlation", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 92-108", "weight": 1.0}, {"source": "cm_proxy_bidirectional_proxy_handler", "target": "cm_proxy_bidirectional_proxy_cmproxystatemachine", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 121-128", "weight": 1.0}, {"source": "cm_proxy_bidirectional_proxy_cmproxystatemachine", "target": "cm_proxy_bidirectional_proxy_enqueuerequest", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 98-108", "weight": 1.0}, {"source": "cm_proxy_bidirectional_proxy_enqueuerequest", "target": "cm_proxy_bidirectional_proxy_cmproxyrequestqueue", "relation": "shares_data_with", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 103-107", "weight": 1.0}, {"source": "cm_proxy_bidirectional_proxy_cmproxyurl", "target": "cm_proxy_bidirectional_proxy_cmproxyfunction", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 139-143", "weight": 1.0}, {"source": "cm_proxy_bidirectional_proxy_cmproxyfunction", "target": "cm_proxy_bidirectional_proxy_lambdarole", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "line 137", "weight": 1.0}, {"source": "cm_proxy_bidirectional_proxy_cmproxystatemachine", "target": "cm_proxy_bidirectional_proxy_statemachinerole", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "line 95", "weight": 1.0}, {"source": "cm_proxy_bidirectional_proxy_statemachinerole", "target": "cm_proxy_bidirectional_proxy_cmproxyrequestqueue", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 31-40", "weight": 1.0}, {"source": "cm_proxy_bidirectional_proxy_lambdarole", "target": "cm_proxy_bidirectional_proxy_permissionsboundary", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 53-56", "weight": 1.0}, {"source": "cm_proxy_bidirectional_proxy_statemachinerole", "target": "cm_proxy_bidirectional_proxy_permissionsboundary", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "cm_proxy/bidirectional-proxy.yaml", "source_location": "lines 26-29", "weight": 1.0}], "hyperedges": [{"id": "bidirectional_request_response_flow", "label": "Bidirectional proxy request/response flow", "nodes": ["cm_proxy_bidirectional_proxy_cmproxyurl", "cm_proxy_bidirectional_proxy_handler", "cm_proxy_bidirectional_proxy_cmproxystatemachine", "cm_proxy_bidirectional_proxy_enqueuerequest", "cm_proxy_bidirectional_proxy_cmproxyrequestqueue", "docs_how_it_works_task_token_correlation"], "relation": "participate_in", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "cm_proxy/bidirectional-proxy.yaml"}]} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/eb5b247f4fc82f461d5e07d9f2d5c5efe7078855d5aeadc3c884eed570dc1967.json b/graphify-out/cache/semantic/pd5fd89c46bb5/eb5b247f4fc82f461d5e07d9f2d5c5efe7078855d5aeadc3c884eed570dc1967.json new file mode 100644 index 0000000..f59bab8 --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/eb5b247f4fc82f461d5e07d9f2d5c5efe7078855d5aeadc3c884eed570dc1967.json @@ -0,0 +1 @@ +{"nodes": [{"id": "proxy_role_cmproxypermissionsboundary", "label": "CMProxyPermissionsBoundary managed policy", "file_type": "code", "source_file": "proxy-role.yaml", "source_location": "lines 7-37", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Caps what any cm-proxy-created role can ever do, scoped by ARN patterns to *-CMProxyRequestQueue-*, CMProxyStateMachine-* and *-CMProxyFunction-* log groups. Region-scoped ARNs are why cm-proxy is limited to one AWS region under least privilege."}, {"id": "proxy_role_cmproxycloudformationservicerole", "label": "CMProxyCloudformationServiceRole", "file_type": "code", "source_file": "proxy-role.yaml", "source_location": "lines 47-151", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "CloudFormation assumes this role instead of the user's credentials, so the user never needs iam:CreateRole directly. Role creation is gated on a condition that the permissions boundary is attached, and iam:PassRole is limited by AssociatedResourceARN to the proxy lambda and state machine."}, {"id": "proxy_role_cmproxypolicy", "label": "CMProxyPolicy managed policy (cm-proxy-policy)", "file_type": "code", "source_file": "proxy-role.yaml", "source_location": "lines 161-199", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "The policy attached to the human/CI identity running cm-proxy: read the two SSM parameters, manage only cm-proxy* stacks, pass the CFN service role, and receive/delete queue messages plus states:SendTaskSuccess for returning bidirectional responses."}, {"id": "proxy_role_cmproxypermissionsboundaryparameter", "label": "SSM parameter /cm-proxy/permissions-boundary", "file_type": "code", "source_file": "proxy-role.yaml", "source_location": "lines 39-45", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "SSM is used as the discovery channel so the CLI can find the boundary ARN at runtime without the user configuring anything."}, {"id": "proxy_role_cmproxycloudformationserviceroleparameter", "label": "SSM parameter /cm-proxy/cloudformation-service-role", "file_type": "code", "source_file": "proxy-role.yaml", "source_location": "lines 153-159", "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "proxy_role_cmproxypermissionsboundary", "target": "cm_proxy_bidirectional_proxy_cmproxyrequestqueue", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "proxy-role.yaml", "source_location": "line 20", "weight": 1.0}, {"source": "proxy_role_cmproxypermissionsboundary", "target": "cm_proxy_unidirectional_proxy_cmproxyrequestqueue", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "proxy-role.yaml", "source_location": "line 20", "weight": 1.0}, {"source": "proxy_role_cmproxypermissionsboundary", "target": "cm_proxy_bidirectional_proxy_cmproxystatemachine", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "proxy-role.yaml", "source_location": "lines 21-28", "weight": 1.0}, {"source": "proxy_role_cmproxypermissionsboundary", "target": "cm_proxy_bidirectional_proxy_cmproxyfunction", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "proxy-role.yaml", "source_location": "lines 29-37", "weight": 1.0}, {"source": "proxy_role_cmproxypermissionsboundary", "target": "cm_proxy_unidirectional_proxy_cmproxyfunction", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "proxy-role.yaml", "source_location": "lines 29-37", "weight": 1.0}, {"source": "cm_proxy_bidirectional_proxy_permissionsboundary", "target": "proxy_role_cmproxypermissionsboundaryparameter", "relation": "shares_data_with", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "proxy-role.yaml", "source_location": "lines 39-45", "weight": 1.0}, {"source": "cm_proxy_unidirectional_proxy_permissionsboundary", "target": "proxy_role_cmproxypermissionsboundaryparameter", "relation": "shares_data_with", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "proxy-role.yaml", "source_location": "lines 39-45", "weight": 1.0}, {"source": "proxy_role_cmproxypermissionsboundaryparameter", "target": "proxy_role_cmproxypermissionsboundary", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "proxy-role.yaml", "source_location": "line 45", "weight": 1.0}, {"source": "proxy_role_cmproxycloudformationserviceroleparameter", "target": "proxy_role_cmproxycloudformationservicerole", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "proxy-role.yaml", "source_location": "line 159", "weight": 1.0}, {"source": "proxy_role_cmproxycloudformationservicerole", "target": "proxy_role_cmproxypermissionsboundary", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "proxy-role.yaml", "source_location": "lines 76-78", "weight": 1.0}, {"source": "proxy_role_cmproxypolicy", "target": "proxy_role_cmproxycloudformationservicerole", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "proxy-role.yaml", "source_location": "lines 182-188", "weight": 1.0}, {"source": "proxy_role_cmproxypolicy", "target": "proxy_role_cmproxypermissionsboundaryparameter", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "proxy-role.yaml", "source_location": "lines 169-173", "weight": 1.0}, {"source": "proxy_role_cmproxypolicy", "target": "proxy_role_cmproxycloudformationserviceroleparameter", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "proxy-role.yaml", "source_location": "lines 169-173", "weight": 1.0}, {"source": "proxy_role_cmproxypolicy", "target": "cm_proxy_bidirectional_proxy_cmproxystatemachine", "relation": "shares_data_with", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "proxy-role.yaml", "source_location": "lines 196-199", "weight": 1.0}, {"source": "proxy_role_cmproxypolicy", "target": "docs_security_least_privilege", "relation": "implements", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "proxy-role.yaml", "source_location": "lines 161-199", "weight": 1.0}], "hyperedges": [{"id": "least_privilege_iam_scaffold", "label": "Least-privilege IAM scaffold for cm-proxy deployment", "nodes": ["proxy_role_cmproxypermissionsboundary", "proxy_role_cmproxycloudformationservicerole", "proxy_role_cmproxypolicy", "proxy_role_cmproxypermissionsboundaryparameter", "proxy_role_cmproxycloudformationserviceroleparameter", "docs_security_least_privilege"], "relation": "implement", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "proxy-role.yaml"}]} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/f772544d5086d191ec98480c8d6ef9605ec5a723ce61df408e0f5d1918afc705.json b/graphify-out/cache/semantic/pd5fd89c46bb5/f772544d5086d191ec98480c8d6ef9605ec5a723ce61df408e0f5d1918afc705.json new file mode 100644 index 0000000..a1a41dd --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/f772544d5086d191ec98480c8d6ef9605ec5a723ce61df408e0f5d1918afc705.json @@ -0,0 +1 @@ +{"nodes": [{"id": "changelog_0_2_4", "label": "Release 0.2.4 (hop-by-hop header strip)", "file_type": "document", "source_file": "CHANGELOG.rst", "source_location": "lines 4-8", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Hop-by-hop response headers had to be stripped in the bidirectional proxy because forwarding them caused Step Functions HTTP Invoke chunked-encoding timeouts."}, {"id": "changelog_0_2_3", "label": "Release 0.2.3 (python3.14 / arm64)", "file_type": "document", "source_file": "CHANGELOG.rst", "source_location": "lines 10-16", "source_url": null, "captured_at": null, "author": null, "contributor": null, "rationale": "Moved lambdas to the python3.14 runtime and arm64 architecture, and published the cost estimate, all of which reduce per-request cost."}], "edges": [{"source": "changelog_0_2_4", "target": "cm_proxy_bidirectional_proxy_cmproxyfunction", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "CHANGELOG.rst", "source_location": "line 8", "weight": 1.0}, {"source": "changelog_0_2_3", "target": "cm_proxy_unidirectional_proxy_cmproxyfunction", "relation": "references", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "CHANGELOG.rst", "source_location": "lines 14-16", "weight": 1.0}, {"source": "changelog_0_2_3", "target": "docs_cost_cost_estimate", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "CHANGELOG.rst", "source_location": "line 16", "weight": 1.0}], "hyperedges": []} \ No newline at end of file diff --git a/graphify-out/cache/semantic/pd5fd89c46bb5/f7dea855e503700d1596788b23ed5831f370a82a8bdd93a26867653c7e8f05b1.json b/graphify-out/cache/semantic/pd5fd89c46bb5/f7dea855e503700d1596788b23ed5831f370a82a8bdd93a26867653c7e8f05b1.json new file mode 100644 index 0000000..192b7ad --- /dev/null +++ b/graphify-out/cache/semantic/pd5fd89c46bb5/f7dea855e503700d1596788b23ed5831f370a82a8bdd93a26867653c7e8f05b1.json @@ -0,0 +1 @@ +{"nodes": [{"id": "docs_images_unidirectional_proxy_diagram", "label": "Unidirectional Proxy Architecture Diagram", "file_type": "image", "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_aws_boundary", "label": "AWS (cloud boundary)", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_local_dev_host", "label": "Local Dev Host (boundary)", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_incoming_request", "label": "Incoming Request", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_lambda", "label": "Lambda", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_request_queue", "label": "Request Queue (SQS)", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_receivemessage", "label": "ReceiveMessage (queue poll)", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_cm_proxy", "label": "cm-proxy", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_mitmproxy", "label": "mitmproxy", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_local_server", "label": "Local Server", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_http", "label": "http (local transport hop)", "file_type": "concept", "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}, {"id": "docs_images_unidirectional_proxy_unidirectional_flow", "label": "Unidirectional Flow (queue-pulled requests, no inbound connection to local host)", "file_type": "rationale", "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "source_url": null, "captured_at": null, "author": null, "contributor": null}], "edges": [{"source": "docs_images_unidirectional_proxy_diagram", "target": "docs_images_unidirectional_proxy_unidirectional_flow", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_incoming_request", "target": "docs_images_unidirectional_proxy_lambda", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_lambda", "target": "docs_images_unidirectional_proxy_request_queue", "relation": "shares_data_with", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_cm_proxy", "target": "docs_images_unidirectional_proxy_request_queue", "relation": "shares_data_with", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_cm_proxy", "target": "docs_images_unidirectional_proxy_receivemessage", "relation": "calls", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_receivemessage", "target": "docs_images_unidirectional_proxy_request_queue", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_cm_proxy", "target": "docs_images_unidirectional_proxy_mitmproxy", "relation": "shares_data_with", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_mitmproxy", "target": "docs_images_unidirectional_proxy_local_server", "relation": "shares_data_with", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_http", "target": "docs_images_unidirectional_proxy_local_server", "relation": "references", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_lambda", "target": "docs_images_unidirectional_proxy_aws_boundary", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_request_queue", "target": "docs_images_unidirectional_proxy_aws_boundary", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_cm_proxy", "target": "docs_images_unidirectional_proxy_local_dev_host", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_mitmproxy", "target": "docs_images_unidirectional_proxy_local_dev_host", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_local_server", "target": "docs_images_unidirectional_proxy_local_dev_host", "relation": "conceptually_related_to", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_unidirectional_flow", "target": "docs_images_unidirectional_proxy_cm_proxy", "relation": "rationale_for", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_unidirectional_flow", "target": "docs_images_unidirectional_proxy_request_queue", "relation": "rationale_for", "confidence": "INFERRED", "confidence_score": 0.85, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_lambda", "target": "docs_images_unidirectional_proxy_cm_proxy", "relation": "conceptually_related_to", "confidence": "INFERRED", "confidence_score": 0.95, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}, {"source": "docs_images_unidirectional_proxy_mitmproxy", "target": "docs_images_unidirectional_proxy_cm_proxy", "relation": "semantically_similar_to", "confidence": "INFERRED", "confidence_score": 0.75, "source_file": "docs/images/unidirectional-proxy.svg", "source_location": null, "weight": 1.0}], "hyperedges": [{"id": "unidirectional_request_delivery_path", "label": "Unidirectional request delivery path: incoming request to Lambda to queue, pulled by cm-proxy", "nodes": ["docs_images_unidirectional_proxy_incoming_request", "docs_images_unidirectional_proxy_lambda", "docs_images_unidirectional_proxy_request_queue", "docs_images_unidirectional_proxy_receivemessage", "docs_images_unidirectional_proxy_cm_proxy"], "relation": "participate_in", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg"}, {"id": "local_dev_host_forwarding_chain", "label": "Local dev host forwarding chain: cm-proxy to mitmproxy to local server over http", "nodes": ["docs_images_unidirectional_proxy_cm_proxy", "docs_images_unidirectional_proxy_mitmproxy", "docs_images_unidirectional_proxy_local_server", "docs_images_unidirectional_proxy_http"], "relation": "form", "confidence": "EXTRACTED", "confidence_score": 1.0, "source_file": "docs/images/unidirectional-proxy.svg"}]} \ No newline at end of file