@dataparade/cli 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +24 -0
  2. package/dist/package.json +85 -0
  3. package/dist/src/ai-enrichment/agent-orchestrator.d.ts +2 -0
  4. package/dist/src/ai-enrichment/agent-orchestrator.js +8 -5
  5. package/dist/src/ai-enrichment/providers/hosted-worker-infer-provider.d.ts +10 -0
  6. package/dist/src/ai-enrichment/providers/hosted-worker-infer-provider.js +47 -0
  7. package/dist/src/cli.js +85 -1
  8. package/dist/src/config/env.js +2 -0
  9. package/dist/src/config/resolve.js +3 -0
  10. package/dist/src/config/scan-env.d.ts +1 -0
  11. package/dist/src/config/scan-env.js +5 -0
  12. package/dist/src/config/types.d.ts +1 -0
  13. package/dist/src/config/upload-env.d.ts +1 -0
  14. package/dist/src/config/upload-env.js +10 -0
  15. package/dist/src/config/validate-scan-ai.d.ts +1 -1
  16. package/dist/src/config/validate-scan-ai.js +5 -0
  17. package/dist/src/core/pipeline/ai-orchestrator-options.js +5 -0
  18. package/dist/src/core/schema/scan-config.schema.d.ts +2 -0
  19. package/dist/src/core/schema/scan-config.schema.js +2 -1
  20. package/dist/src/core/types/config.d.ts +3 -1
  21. package/dist/src/observability/scan-sentry.d.ts +1 -1
  22. package/dist/src/platform-api/dataparade-app-base-url.d.ts +7 -0
  23. package/dist/src/platform-api/dataparade-app-base-url.js +14 -0
  24. package/dist/src/platform-api/upload-client.d.ts +3 -0
  25. package/dist/src/platform-api/upload-client.js +38 -0
  26. package/dist/src/platform-api/upload.types.d.ts +10 -0
  27. package/dist/src/platform-api/upload.types.js +2 -0
  28. package/dist/src/upload/build-preview-url.d.ts +1 -0
  29. package/dist/src/upload/build-preview-url.js +10 -0
  30. package/dist/src/upload/run-upload.d.ts +2 -0
  31. package/dist/src/upload/run-upload.js +18 -0
  32. package/dist/src/upload/types.d.ts +11 -0
  33. package/dist/src/upload/types.js +2 -0
  34. package/dist/tests/unit/cli/scan-quota-flow.spec.js +2 -0
  35. package/dist/tests/unit/config/upload-env.spec.d.ts +1 -0
  36. package/dist/tests/unit/config/upload-env.spec.js +12 -0
  37. package/dist/tests/unit/config/validate-scan-ai.spec.js +8 -0
  38. package/dist/tests/unit/platform-api/dataparade-app-base-url.spec.d.ts +1 -0
  39. package/dist/tests/unit/platform-api/dataparade-app-base-url.spec.js +13 -0
  40. package/dist/tests/unit/platform-api/upload-client.spec.d.ts +1 -0
  41. package/dist/tests/unit/platform-api/upload-client.spec.js +40 -0
  42. package/dist/tests/unit/publish-manifest.spec.d.ts +1 -0
  43. package/dist/tests/unit/publish-manifest.spec.js +18 -0
  44. package/dist/tests/unit/upload/build-preview-url.spec.d.ts +1 -0
  45. package/dist/tests/unit/upload/build-preview-url.spec.js +19 -0
  46. package/package.json +4 -3
  47. package/patterns/README.md +322 -0
  48. package/patterns/actor.patterns.yaml +51 -0
  49. package/patterns/aws-terraform-catalog.snapshot.json +1760 -0
  50. package/patterns/aws-terraform-service-hints.generated.json +1446 -0
  51. package/patterns/azure-terraform-catalog.snapshot.json +1195 -0
  52. package/patterns/azure-terraform-service-hints.generated.json +864 -0
  53. package/patterns/classifier/actors.classifier.yaml +17 -0
  54. package/patterns/classifier/components.classifier.yaml +110 -0
  55. package/patterns/classifier/third-party.classifier.yaml +169 -0
  56. package/patterns/kubernetes-terraform-catalog.snapshot.json +94 -0
  57. package/patterns/kubernetes-terraform-service-hints.generated.json +258 -0
  58. package/patterns/non-pii-signals.rules.yaml +84 -0
  59. package/patterns/pii-signals.rules.yaml +115 -0
  60. package/patterns/property.patterns.yaml +431 -0
  61. package/patterns/provider-topology.rules.yaml +765 -0
  62. package/patterns/python.md +211 -0
  63. package/patterns/python.patterns.yaml +160 -0
  64. package/patterns/terraform.md +37 -0
  65. package/patterns/terraform.patterns.yaml +495 -0
  66. package/patterns/third-party.patterns.yaml +167 -0
  67. package/patterns/typescript.patterns.yaml +139 -0
@@ -0,0 +1,211 @@
1
+ # Python Patterns (CLI Scanner)
2
+
3
+ This document describes the Python-specific patterns implemented by the CLI codebase scanner for **DP-P0-CLI-703 – Python pattern detector**.
4
+
5
+ The Python analyzer emits `RawFinding[]` using the **shared pattern IDs** from `core/types/detection.ts`:
6
+
7
+ - `express_route`
8
+ - `database_connection`
9
+ - `external_api_call`
10
+ - `auth_middleware`
11
+ - `config_file`
12
+ - `env_variable`
13
+
14
+ These pattern IDs align with the TypeScript/JavaScript analyzer so that the classifier and data-flow detector can treat Python and TS/JS findings consistently.
15
+
16
+ ## Route / Handler Detection (`express_route`)
17
+
18
+ The Python analyzer reuses the `express_route` pattern ID for web routes and handlers in common Python web frameworks.
19
+
20
+ ### FastAPI
21
+
22
+ - **Detected when:**
23
+ - The module imports `FastAPI` or any symbol from `fastapi`.
24
+ - A function has a decorator starting with `app.get`, `app.post`, `app.put`, `app.delete`, or `app.patch`.
25
+ - **Emitted finding:**
26
+ - `pattern`: `express_route`
27
+ - `name`: `"<METHOD> <function_name>"` (e.g. `GET read_item`)
28
+ - `properties`:
29
+ - `framework`: `"fastapi"`
30
+ - `httpMethods`: `[ "<METHOD>" ]`
31
+
32
+ **Example:**
33
+
34
+ ```python
35
+ from fastapi import FastAPI
36
+
37
+ app = FastAPI()
38
+
39
+ @app.get("/items/{item_id}")
40
+ async def read_item(item_id: int):
41
+ ...
42
+ ```
43
+
44
+ ### Flask
45
+
46
+ - **Detected when:**
47
+ - The module imports from `flask` or imports `Flask`.
48
+ - A function has a decorator starting with `app.route`, `bp.route`, or `blueprint.route`.
49
+ - **Emitted finding:**
50
+ - `pattern`: `express_route`
51
+ - `name`: `"FLASK_ROUTE <function_name>"`
52
+ - `properties`:
53
+ - `framework`: `"flask"`
54
+
55
+ **Example:**
56
+
57
+ ```python
58
+ from flask import Flask
59
+
60
+ app = Flask(__name__)
61
+
62
+ @app.route("/users", methods=["GET"])
63
+ def list_users():
64
+ ...
65
+ ```
66
+
67
+ ### Django / Django REST Framework
68
+
69
+ - **Detected when:**
70
+ - The file path ends with `urls.py` or imports start with `django.`.
71
+ - A line contains `path("...")`, `re_path("...")`, or `url("...")`.
72
+ - **Emitted finding:**
73
+ - `pattern`: `express_route`
74
+ - `name`: `"DJANGO_ROUTE <path>"`
75
+ - `properties`:
76
+ - `framework`: `"django"`
77
+ - `path`: `"<route_path>"`
78
+
79
+ **Example (`urls.py`):**
80
+
81
+ ```python
82
+ from django.urls import path
83
+ from . import views
84
+
85
+ urlpatterns = [
86
+ path("users/", views.user_list, name="user-list"),
87
+ ]
88
+ ```
89
+
90
+ ### Starlette
91
+
92
+ - **Detected when:**
93
+ - The module imports Starlette (module name contains `"starlette"`).
94
+ - A function has a decorator starting with `app.route`.
95
+ - **Emitted finding:**
96
+ - `pattern`: `express_route`
97
+ - `name`: `"STARLETTE_ROUTE <function_name>"`
98
+ - `properties`:
99
+ - `framework`: `"starlette"`
100
+
101
+ ### Bottle
102
+
103
+ - **Detected when:**
104
+ - The module imports from `bottle` or imports `Bottle`.
105
+ - A function has decorators `@route`, `@get`, `@post`, `@put`, or `@delete`.
106
+ - **Emitted finding:**
107
+ - `pattern`: `express_route`
108
+ - `name`: `"BOTTLE_ROUTE <function_name>"`
109
+ - `properties`:
110
+ - `framework`: `"bottle"`
111
+
112
+ ## Database / ORM Detection (`database_connection`)
113
+
114
+ The Python analyzer emits `database_connection` for database clients and ORM usage.
115
+
116
+ ### psycopg2
117
+
118
+ - **Detected when:**
119
+ - The module imports from `psycopg2` / `psycopg`.
120
+ - A module-level call contains `connect` (e.g. `psycopg2.connect(...)`).
121
+ - **Properties:**
122
+ - `client`: `"psycopg2"`
123
+ - `databaseType`: `"postgres"`
124
+
125
+ ### SQLAlchemy
126
+
127
+ - **Detected when:**
128
+ - The module imports from `sqlalchemy` or imports `create_engine`.
129
+ - A module-level call contains `create_engine`.
130
+ - **Properties:**
131
+ - `client`: `"sqlalchemy"`
132
+ - `databaseType`: `"sql"`
133
+
134
+ ### Django ORM
135
+
136
+ - **Detected when:**
137
+ - The module imports from `django.db` or the content includes `.objects.`.
138
+ - **Properties:**
139
+ - `client`: `"django_orm"`
140
+ - `databaseType`: `"sql"`
141
+
142
+ ## External HTTP / API Calls (`external_api_call`)
143
+
144
+ The Python analyzer emits `external_api_call` for HTTP clients and SDKs.
145
+
146
+ ### HTTP client libraries
147
+
148
+ - **requests**
149
+ - Detected when the module imports `requests` and a module-level call starts with `requests.`.
150
+ - `name`: `"requests_call"`
151
+ - `properties.url`: first `http(s)` URL literal found in the file, if any.
152
+
153
+ - **httpx**
154
+ - Detected when the module imports `httpx` and a module-level call starts with `httpx.`.
155
+ - `name`: `"httpx_call"`
156
+
157
+ - **aiohttp**
158
+ - Detected when the module imports `aiohttp` or `ClientSession` and a module-level call references `ClientSession` or `.get`.
159
+ - `name`: `"aiohttp_call"`
160
+
161
+ ### SDKs
162
+
163
+ The analyzer also emits `external_api_call` findings when the module imports:
164
+
165
+ - `boto3` → `name`: `"boto3_client"`, `serviceName`: `"aws"`
166
+ - `stripe` → `name`: `"stripe_sdk"`, `serviceName`: `"stripe"`
167
+ - `sendgrid` → `name`: `"sendgrid_sdk"`, `serviceName`: `"sendgrid"`
168
+ - `twilio` → `name`: `"twilio_sdk"`, `serviceName`: `"twilio"`
169
+ - `openai` → `name`: `"openai_sdk"`, `serviceName`: `"openai"`
170
+
171
+ ## Auth Patterns (`auth_middleware`)
172
+
173
+ The Python analyzer emits `auth_middleware` findings for common auth patterns.
174
+
175
+ - **JWT-based auth**
176
+ - Detected when:
177
+ - The module imports a module containing `"jwt"`, imports `jwt`, or
178
+ - The content includes `jwt.encode(` or `jwt.decode(`.
179
+ - `name`: `"jwt_auth"`
180
+ - `properties.strategy`: `"jwt"`
181
+
182
+ - **Auth decorators / permissions**
183
+ - Detected when module-level calls reference `login_required` or `IsAuthenticated`.
184
+ - `name`: `"auth_decorator"`
185
+
186
+ - **Generic auth libraries**
187
+ - Detected when imports contain `"auth"` or `"authentication"`.
188
+ - `name`: `"auth_library"`
189
+
190
+ ## Config and Environment (`config_file`, `env_variable`)
191
+
192
+ ### Environment variables (`env_variable`)
193
+
194
+ - **Detected when:**
195
+ - The module imports `os`, and lines reference:
196
+ - `os.environ["KEY"]` or `os.environ['KEY']`
197
+ - `os.getenv("KEY")` or `os.getenv('KEY')`
198
+ - **Emitted finding:**
199
+ - `pattern`: `env_variable`
200
+ - `name`: `"os.environ[KEY]"`
201
+ - `properties.key`: `"KEY"`
202
+
203
+ ### Config files (`config_file`)
204
+
205
+ - **Django settings**
206
+ - Detected when the file path ends with `settings.py`.
207
+ - `name`: `"django_settings"`
208
+
209
+ - **dotenv configuration**
210
+ - Detected when the module imports `os` and the content includes `load_dotenv(`.
211
+ - `name`: `"dotenv_config"`
@@ -0,0 +1,160 @@
1
+ # Python pattern config. All entries share: patternId, optional confidence (default 0.8).
2
+
3
+ db_clients:
4
+ - id: psycopg2
5
+ patternId: database_connection
6
+ databaseType: postgres
7
+ importModules:
8
+ - psycopg2
9
+ - psycopg
10
+ callNames:
11
+ - connect
12
+ confidence: 0.9
13
+
14
+ - id: sqlalchemy
15
+ patternId: database_connection
16
+ databaseType: sql
17
+ importModules:
18
+ - sqlalchemy
19
+ callNames:
20
+ - create_engine
21
+ confidence: 0.9
22
+
23
+ - id: django_orm
24
+ patternId: database_connection
25
+ databaseType: sql
26
+ importModules:
27
+ - django.db
28
+ heuristics:
29
+ usesObjectsAttribute: true
30
+ confidence: 0.85
31
+
32
+ auth:
33
+ jwt:
34
+ patternId: auth_middleware
35
+ importModules:
36
+ - jwt
37
+ contentRegexes:
38
+ - "jwt\\.encode\\("
39
+ - "jwt\\.decode\\("
40
+ strategy: jwt
41
+ confidence: 0.85
42
+
43
+ decorators:
44
+ - id: login_required
45
+ patternId: auth_middleware
46
+ callNames:
47
+ - login_required
48
+ confidence: 0.8
49
+ - id: is_authenticated
50
+ patternId: auth_middleware
51
+ callNames:
52
+ - IsAuthenticated
53
+ confidence: 0.8
54
+
55
+ routes:
56
+ frameworks:
57
+ - id: fastapi
58
+ patternId: express_route
59
+ importModules:
60
+ - fastapi
61
+ decoratorPrefixes:
62
+ - app.get
63
+ - app.post
64
+ - app.put
65
+ - app.delete
66
+ - app.patch
67
+ confidence: 0.9
68
+
69
+ - id: flask
70
+ patternId: express_route
71
+ importModules:
72
+ - flask
73
+ decoratorPrefixes:
74
+ - app.route
75
+ - bp.route
76
+ - blueprint.route
77
+ confidence: 0.9
78
+
79
+ - id: starlette
80
+ patternId: express_route
81
+ importModules:
82
+ - starlette
83
+ decoratorPrefixes:
84
+ - app.route
85
+ confidence: 0.85
86
+
87
+ - id: bottle
88
+ patternId: express_route
89
+ importModules:
90
+ - bottle
91
+ decoratorNames:
92
+ - route
93
+ - get
94
+ - post
95
+ - put
96
+ - delete
97
+ confidence: 0.85
98
+
99
+ - id: django_urls
100
+ patternId: express_route
101
+ importModules:
102
+ - django.
103
+ urlsFileSuffix: "urls.py"
104
+ pathRegex: "(path|re_path|url)\\(\\s*['\\\"]([^'\\\"]+)['\\\"]"
105
+ confidence: 0.9
106
+
107
+ env_config:
108
+ envVariable:
109
+ patternId: env_variable
110
+ regex: "os\\.(environ\\[['\\\"][^'\\\"]+['\\\"]\\]|getenv\\(\\s*['\\\"][^'\\\"]+['\\\"])"
111
+ confidence: 0.85
112
+
113
+ djangoSettings:
114
+ patternId: config_file
115
+ fileSuffix: "settings.py"
116
+ name: django_settings
117
+ confidence: 0.9
118
+
119
+ dotenvConfig:
120
+ patternId: config_file
121
+ requiresOsImport: true
122
+ contentSubstring: "load_dotenv("
123
+ name: dotenv_config
124
+ confidence: 0.85
125
+
126
+ external_apis:
127
+ httpClients:
128
+ - id: requests
129
+ patternId: external_api_call
130
+ clientName: requests
131
+ importModules:
132
+ - requests
133
+ urlRegex: "['\\\"](https?:\\/\\/[^\\s'\\\"]+)['\\\"]"
134
+ confidence: 0.85
135
+
136
+ - id: httpx
137
+ patternId: external_api_call
138
+ clientName: httpx
139
+ importModules:
140
+ - httpx
141
+ urlRegex: "['\\\"](https?:\\/\\/[^\\s'\\\"]+)['\\\"]"
142
+ confidence: 0.85
143
+
144
+ - id: aiohttp
145
+ patternId: external_api_call
146
+ clientName: aiohttp
147
+ importModules:
148
+ - aiohttp
149
+ urlRegex: "['\\\"](https?:\\/\\/[^\\s'\\\"]+)['\\\"]"
150
+ confidence: 0.85
151
+
152
+ - id: supabase_python
153
+ patternId: external_api_call
154
+ clientName: supabase
155
+ importModules:
156
+ - supabase
157
+ callNames:
158
+ - create_client
159
+ confidence: 0.85
160
+
@@ -0,0 +1,37 @@
1
+ # Terraform patterns (CLI)
2
+
3
+ The Terraform analyzer performs **static, best-effort** parsing of `.tf` and `.tfvars` files. It does **not** run `terraform` or evaluate full HCL2 (heredocs, complex expressions, and `dynamic` blocks may be incomplete).
4
+
5
+ **All matching rules** (block openers, cross-reference regexes, resource-type → `componentSubType` / `cloud_provider` hints, provider display names, and **satellite** resources folded into a parent) live in [`terraform.patterns.yaml`](terraform.patterns.yaml) and are loaded via `terraform-detection-config.ts`, consistent with `typescript.patterns.yaml` / `python.patterns.yaml`.
6
+
7
+ **AWS resource type coverage:** hand-written regex hints in YAML are merged with **`aws-terraform-service-hints.generated.json`**, produced from **`@cdktf/provider-aws`** (tracks HashiCorp **[`terraform-provider-aws`](https://github.com/hashicorp/terraform-provider-aws)** ~> 6.x) and listing **~1.7k** `aws_*` strings in **`aws-terraform-catalog.snapshot.json`**. Generated `^aws_<service>_` rows are inserted immediately before the generic `^aws_` rule so uncommon services get a sensible `componentSubType` instead of falling through to `application`.
8
+
9
+ **Azure (`azurerm`) resource type coverage:** **`azure-terraform-service-hints.generated.json`** + **`azure-terraform-catalog.snapshot.json`** come from **`@cdktf/provider-azurerm`** (~1.2k `azurerm_*` types), which tracks the upstream **[`hashicorp/terraform-provider-azurerm`](https://github.com/hashicorp/terraform-provider-azurerm)** Azure Resource Manager provider; hints are merged before **`azurerm_default_family`**. The **`azapi_*`** provider has no CDKTF package in this flow; it stays covered by the hand-written **`^azapi_`** rule in [`terraform.patterns.yaml`](terraform.patterns.yaml).
10
+
11
+ **Kubernetes resource type coverage:** **`kubernetes-terraform-service-hints.generated.json`** + **`kubernetes-terraform-catalog.snapshot.json`** come from **`@cdktf/provider-kubernetes`** (HashiCorp **`kubernetes_*`** resources for in-cluster workloads, services, ingress, secrets, PVCs, etc.); hints merge before **`kubernetes_default_family`**. Provider topology in **`provider-topology.rules.yaml`** maps **`provider "kubernetes"`** to managed nodes (workload, service, ingress, config, storage, namespace).
12
+
13
+ Regenerate all provider snapshots from `cli/` with **`pnpm run generate:terraform-provider-hints`** (or AWS / Azure / Kubernetes only — see **`cli/README.md`**).
14
+
15
+ ## Pattern IDs
16
+
17
+ | Pattern ID | Meaning |
18
+ |---|---|
19
+ | `terraform_resource` | `resource` or `data` block (address `type.name` or `data.type.name`). |
20
+ | `terraform_module` | `module` block. |
21
+ | `terraform_provider` | `provider` block (emitted as a `third_party` component). |
22
+
23
+ ## Finding properties (representative)
24
+
25
+ - `terraform_address`: stable resource key used for cross-reference flow edges.
26
+ - `terraform_references`: other addresses referenced from the block body (string array), including references from **merged satellite** blocks (see below).
27
+ - `terraform_satellites` (optional): when a child resource is configured as a **satellite** of a primary resource in YAML (e.g. S3 ACL / ownership controls scoped by `bucket = …`), it is **not** emitted as its own node; metadata is attached here on the parent finding.
28
+ - `resource_type`, `block_name`, `cloud_provider`, `componentSubType` (classifier hint).
29
+ - `section_id` / `section_label`: derived from the file path for layout grouping.
30
+ - After **`applyDeterministicInferenceFallbacks`** (same pipeline step as TypeScript scans), matching AWS/Azure/Kubernetes/… resources may also have **`managed_by_provider`**, **`managed_service_key`**, and **`generated_by: "provider_topology_fallback"`** when they align with `provider-topology.rules.yaml` managed service nodes (e.g. labels **Aws S3**, **Aws Lambda**, **Kubernetes workload**). This mirrors TS SDK topology and enables the same provider→managed edge styling in graph export. Resources not covered by a managed node still get a **`provider → resource`** `api_call` via **`appendTerraformBareProviderAttachmentFlows`** inside that fallback pass.
31
+
32
+ ## Provider topology (parity with TypeScript)
33
+
34
+ Static Terraform scans do **not** run a second topology engine. The **same** function, **`applyDeterministicInferenceFallbacks`** (`cli/src/ai-enrichment/fallbacks.ts`), loads **`cli/patterns/provider-topology.rules.yaml`**. For **TypeScript/JavaScript**, usage signals come from **`providerUsageCorpus(provider, flows)`**. For **Terraform on AWS**, each `managedServiceNode` lists **`terraformResourceTypePrefixes`** / **`terraformResourceTypes`** (HashiCorp `aws_*` resource type names, e.g. `aws_s3_bucket`, prefix `aws_lambda_`); matching uses **`resource_type` only**, not block labels like `lambda_bucket`. Providers without those fields (e.g. Supabase) still use legacy **`usageSignals`** matching on Terraform metadata. Shared helpers: **`cli/src/ai-enrichment/provider-topology-shared.ts`**. **`componentMatchesProvider`** treats Terraform’s **`provider_name`** (e.g. `aws`) as a match key so `provider "aws"` nodes participate in the AWS rule.
35
+
36
+ - References inside `module.*` outputs are not resolved.
37
+ - Optional merge from plan/state: **`terraform show -json`** via CLI `--terraform-json` / `--terraform-plan` (see `cli/README.md` and Epic 29 task DP-P0-CLI-906).