@grafema/types 0.2.5-beta → 0.2.7

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.
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Infrastructure Types — abstract resource taxonomy and cross-layer mapping.
3
+ *
4
+ * USG (Universal System Graph) extends Grafema from code-only to multi-layer:
5
+ * Code → Abstract Resources → Concrete Infrastructure
6
+ *
7
+ * This module defines:
8
+ * - Abstract resource types (tool-agnostic: compute:service, storage:database:sql)
9
+ * - InfraResourceMap interface (like RoutingMap but for infra identity resolution)
10
+ * - Supporting types for analyzers and cross-layer linking
11
+ */
12
+
13
+ import type { Resource } from './resources.js';
14
+ import type { EdgeType } from './edges.js';
15
+
16
+ // ============================================================
17
+ // ABSTRACT RESOURCE TYPE TAXONOMY
18
+ // ============================================================
19
+
20
+ /**
21
+ * Known abstract resource types, organized by category.
22
+ * These are tool-agnostic — K8s Deployment, Docker service, EC2 all map
23
+ * to the same abstract type (compute:service).
24
+ *
25
+ * Convention: category:subcategory[:detail]
26
+ */
27
+ type KnownResourceType =
28
+ // --- Compute ---
29
+ | 'compute:service' // Long-running process (K8s Deployment, ECS Service, Docker service)
30
+ | 'compute:serverless' // FaaS (AWS Lambda, GCP Cloud Function, Azure Function)
31
+ | 'compute:container' // Container instance (ECS, Cloud Run, Container Instances)
32
+ | 'compute:container:orchestration' // K8s cluster (EKS, GKE, AKS)
33
+ | 'compute:job' // Batch/scheduled (K8s CronJob, AWS Batch, Cloud Scheduler)
34
+ | 'compute:vm' // Virtual machine (EC2, Compute Engine, Azure VM)
35
+ // --- Networking ---
36
+ | 'networking:ingress' // Load balancer / entry point (ALB, Cloud LB, App Gateway)
37
+ | 'networking:service' // Internal service (K8s Service, ELB, internal LB)
38
+ | 'networking:gateway' // API Gateway (API GW, Apigee, Azure API Management)
39
+ | 'networking:vpc' // Virtual network (VPC, VNet)
40
+ | 'networking:dns' // DNS (Route53, Cloud DNS, Azure DNS)
41
+ | 'networking:cdn' // CDN (CloudFront, Cloud CDN, Azure CDN)
42
+ | 'networking:firewall' // Firewall / security group (SG, Cloud Armor, NSG)
43
+ | 'networking:vpn' // VPN (VPN Gateway, Cloud VPN)
44
+ // --- Storage ---
45
+ | 'storage:object' // Object/blob (S3, GCS, Blob Storage)
46
+ | 'storage:volume' // Block storage (EBS, Persistent Disk, Managed Disks)
47
+ | 'storage:file' // File system (EFS, Filestore, Azure Files)
48
+ | 'storage:cache' // Cache (ElastiCache, Memorystore, Azure Cache)
49
+ | 'storage:database:sql' // Relational DB (RDS, Cloud SQL, Azure SQL)
50
+ | 'storage:database:nosql' // NoSQL (DynamoDB, Firestore, Cosmos DB)
51
+ | 'storage:database:graph' // Graph DB (Neptune, Cosmos DB Gremlin)
52
+ | 'storage:database:timeseries' // Time-series (Timestream, Azure Data Explorer)
53
+ | 'storage:database:warehouse' // Data warehouse (Redshift, BigQuery, Synapse)
54
+ // --- Messaging ---
55
+ | 'messaging:queue' // Message queue (SQS, Cloud Tasks, Service Bus)
56
+ | 'messaging:stream' // Event stream (Kinesis, Pub/Sub streaming, Event Hubs)
57
+ | 'messaging:topic' // Pub/sub topic (SNS, Pub/Sub, Service Bus Topics)
58
+ | 'messaging:event_bus' // Event bus (EventBridge, Eventarc, Event Grid)
59
+ | 'messaging:workflow' // Workflow orchestration (Step Functions, Workflows, Logic Apps)
60
+ // --- Config ---
61
+ | 'config:map' // Configuration (K8s ConfigMap, Parameter Store, App Config)
62
+ | 'config:secret' // Secrets (K8s Secret, Secrets Manager, Key Vault)
63
+ // --- Security ---
64
+ | 'security:iam' // Identity management (IAM, Cloud IAM, Entra ID)
65
+ | 'security:certificate' // TLS certificates (ACM, Certificate Manager)
66
+ | 'security:dlp' // Data loss prevention (Macie, DLP, Purview)
67
+ | 'security:threat_detection' // Threat detection (GuardDuty, SCC, Defender)
68
+ // --- Observability ---
69
+ | 'observability:alert' // Alert rules (CloudWatch Alarm, Prometheus, Monitor Alerts)
70
+ | 'observability:dashboard' // Dashboards (Grafana, CloudWatch Dashboard)
71
+ | 'observability:slo' // SLO definitions
72
+ | 'observability:log_target' // Log destination (CloudWatch Logs, Cloud Logging)
73
+ | 'observability:tracing' // Distributed tracing (X-Ray, Cloud Trace, App Insights)
74
+ | 'observability:apm' // APM (CloudWatch App Insights, Cloud Profiler)
75
+ // --- DevOps ---
76
+ | 'devops:pipeline' // CI/CD pipeline (CodePipeline, Cloud Build, Azure Pipelines)
77
+ | 'devops:registry:container' // Container registry (ECR, Artifact Registry, ACR)
78
+ | 'devops:iac' // IaC templates (CloudFormation, Deployment Manager, Bicep)
79
+ // --- AI ---
80
+ | 'ai:platform' // ML platform (SageMaker, Vertex AI, Azure ML)
81
+ | 'ai:vision' // Computer vision (Rekognition, Vision AI, Computer Vision)
82
+ | 'ai:nlp' // NLP (Comprehend, Natural Language AI, Text Analytics)
83
+ | 'ai:speech' // Speech (Polly/Transcribe, Speech-to-Text, Azure Speech)
84
+ // --- Communication ---
85
+ | 'communication:email' // Email service (SES, SendGrid)
86
+ | 'communication:sms' // SMS (SNS SMS, Communication Services)
87
+ | 'communication:push' // Push notifications (SNS Mobile, FCM, Notification Hubs)
88
+ // --- IoT ---
89
+ | 'iot:platform' // IoT platform (IoT Core, IoT Hub)
90
+ | 'iot:edge'; // Edge computing (Greengrass, IoT Edge)
91
+
92
+ /**
93
+ * Abstract resource type — known types for autocomplete + extensible via string.
94
+ * Any 'category:subcategory' string is valid.
95
+ */
96
+ export type AbstractResourceType = KnownResourceType | `${string}:${string}`;
97
+
98
+ // ============================================================
99
+ // INFRA RESOURCE MAP
100
+ // ============================================================
101
+
102
+ /** Well-known Resource ID for InfraResourceMap */
103
+ export const INFRA_RESOURCE_MAP_ID = 'infra:resource:map' as const;
104
+
105
+ /**
106
+ * Parsed infrastructure resource from a concrete analyzer.
107
+ * Generic representation before graph node creation.
108
+ */
109
+ export interface InfraResource {
110
+ /** Unique resource ID (e.g., 'infra:k8s:deployment:user-api') */
111
+ id: string;
112
+ /** Concrete tool-specific type (e.g., 'infra:k8s:deployment') */
113
+ type: string;
114
+ /** Human-readable name */
115
+ name: string;
116
+ /** Source file where resource is defined */
117
+ file: string;
118
+ /** Line number in file (if available) */
119
+ line?: number;
120
+ /** Environment(s) this resource belongs to (undefined = all) */
121
+ env?: string | string[];
122
+ /** Tool that created this resource (e.g., 'kubernetes', 'terraform') */
123
+ tool: string;
124
+ /** Raw resource data */
125
+ metadata?: Record<string, unknown>;
126
+ }
127
+
128
+ /**
129
+ * Mapping from concrete resource to abstract type.
130
+ * Created by InfraAnalyzer.mapToAbstract(), stored in InfraResourceMap.
131
+ */
132
+ export interface ResourceMapping {
133
+ /** Concrete graph node ID */
134
+ concreteId: string;
135
+ /** Concrete type (e.g., 'infra:k8s:deployment') */
136
+ concreteType: string;
137
+ /** Abstract type this maps to */
138
+ abstractType: AbstractResourceType;
139
+ /** Abstract resource ID (e.g., 'compute:service:user-api') */
140
+ abstractId: string;
141
+ /** Human-readable name */
142
+ name: string;
143
+ /** Normalized tool-agnostic metadata */
144
+ metadata: Record<string, unknown>;
145
+ /** Environment */
146
+ env?: string | string[];
147
+ /** Source file */
148
+ sourceFile: string;
149
+ /** Tool name */
150
+ sourceTool: string;
151
+ }
152
+
153
+ /**
154
+ * Cross-layer link between code and infrastructure.
155
+ */
156
+ export interface CrossLayerLink {
157
+ type: EdgeType;
158
+ src: string;
159
+ dst: string;
160
+ metadata?: Record<string, unknown>;
161
+ }
162
+
163
+ /**
164
+ * Abstract resource — tool-agnostic representation.
165
+ * Created from one or more concrete resources via InfraResourceMap.
166
+ */
167
+ export interface AbstractResource {
168
+ /** Abstract ID (e.g., 'compute:service:user-api') */
169
+ id: string;
170
+ /** Abstract type */
171
+ type: AbstractResourceType;
172
+ /** Human-readable name */
173
+ name: string;
174
+ /** Environment */
175
+ env?: string | string[];
176
+ /** Normalized metadata */
177
+ metadata: Record<string, unknown>;
178
+ /** Concrete resources that provide this abstract resource */
179
+ providers: ConcreteResourceRef[];
180
+ }
181
+
182
+ /**
183
+ * Reference to a concrete resource that provides an abstract resource.
184
+ */
185
+ export interface ConcreteResourceRef {
186
+ /** Concrete graph node ID */
187
+ id: string;
188
+ /** Tool-specific type */
189
+ type: string;
190
+ /** Tool name */
191
+ tool: string;
192
+ /** Source file */
193
+ file: string;
194
+ }
195
+
196
+ /**
197
+ * InfraResourceMap — maps concrete infrastructure to abstract types.
198
+ * Like RoutingMap but for infrastructure identity resolution.
199
+ *
200
+ * Resource ID: 'infra:resource:map'
201
+ *
202
+ * Lifecycle:
203
+ * 1. Concrete analyzers (K8s, Terraform) call register() during ANALYSIS
204
+ * 2. Enrichers call find*() during ENRICHMENT to create abstract nodes + edges
205
+ */
206
+ export interface InfraResourceMap extends Resource {
207
+ readonly id: typeof INFRA_RESOURCE_MAP_ID;
208
+
209
+ /** Register a concrete->abstract mapping. Called by analyzers. */
210
+ register(mapping: ResourceMapping): void;
211
+
212
+ /** Find abstract resource by name and type. Returns null if not registered. */
213
+ findAbstract(name: string, type: AbstractResourceType): AbstractResource | null;
214
+
215
+ /** Find all concrete resources for an abstract resource ID. */
216
+ findConcrete(abstractId: string): ConcreteResourceRef[];
217
+
218
+ /** Get all abstract resources of a given type. */
219
+ findByType(type: AbstractResourceType): AbstractResource[];
220
+
221
+ /** Filter abstract resources by environment. */
222
+ findByEnv(env: string): AbstractResource[];
223
+
224
+ /** Get all registered abstract resources. */
225
+ getAll(): AbstractResource[];
226
+
227
+ /** Get count of abstract resources (for metrics). */
228
+ get resourceCount(): number;
229
+ }
230
+
231
+ // ============================================================
232
+ // CONFIGURATION SCHEMA
233
+ // ============================================================
234
+
235
+ /**
236
+ * Infrastructure configuration section in grafema.config.yaml.
237
+ *
238
+ * ```yaml
239
+ * infrastructure:
240
+ * enabled: true
241
+ * kubernetes:
242
+ * enabled: true
243
+ * paths: ['k8s/**.yaml']
244
+ * ```
245
+ */
246
+ export interface InfrastructureConfig {
247
+ enabled: boolean;
248
+ kubernetes?: InfraToolConfig;
249
+ terraform?: InfraToolConfig;
250
+ dockerCompose?: InfraToolConfig;
251
+ custom?: CustomAnalyzerConfig;
252
+ }
253
+
254
+ export interface InfraToolConfig {
255
+ enabled: boolean;
256
+ paths: string[];
257
+ mappings?: Record<string, string>;
258
+ }
259
+
260
+ export interface CustomAnalyzerConfig {
261
+ analyzerPath: string;
262
+ }
package/src/nodes.ts CHANGED
@@ -77,6 +77,12 @@ export const NAMESPACED_TYPE = {
77
77
  // Network
78
78
  NET_REQUEST: 'net:request',
79
79
  NET_STDIO: 'net:stdio',
80
+ NET_TCP_CONNECTION: 'net:tcp-connection',
81
+ NET_TCP_SERVER: 'net:tcp-server',
82
+
83
+ // OS-level IPC (Unix domain sockets)
84
+ OS_UNIX_SOCKET: 'os:unix-socket',
85
+ OS_UNIX_SERVER: 'os:unix-server',
80
86
 
81
87
  // Events
82
88
  EVENT_LISTENER: 'event:listener',
@@ -146,6 +152,8 @@ export interface ModuleNodeRecord extends BaseNodeRecord {
146
152
  relativePath: string;
147
153
  contentHash: string;
148
154
  language?: string;
155
+ /** REG-297: true if module uses top-level await */
156
+ hasTopLevelAwait?: boolean;
149
157
  }
150
158
 
151
159
  // Import node
@@ -308,6 +316,40 @@ export interface PluginNodeRecord extends BaseNodeRecord {
308
316
  dependencies: string[];
309
317
  }
310
318
 
319
+ // Unix domain socket client (OS IPC)
320
+ export interface OsUnixSocketNodeRecord extends BaseNodeRecord {
321
+ type: 'os:unix-socket';
322
+ protocol: 'unix';
323
+ path: string;
324
+ library: string;
325
+ }
326
+
327
+ // Unix domain socket server (OS IPC listener)
328
+ export interface OsUnixServerNodeRecord extends BaseNodeRecord {
329
+ type: 'os:unix-server';
330
+ protocol: 'unix';
331
+ path: string;
332
+ backlog?: number;
333
+ }
334
+
335
+ // TCP socket connection (network client)
336
+ export interface NetTcpConnectionNodeRecord extends BaseNodeRecord {
337
+ type: 'net:tcp-connection';
338
+ protocol: 'tcp';
339
+ host?: string;
340
+ port: number;
341
+ library: string;
342
+ }
343
+
344
+ // TCP socket server (network listener)
345
+ export interface NetTcpServerNodeRecord extends BaseNodeRecord {
346
+ type: 'net:tcp-server';
347
+ protocol: 'tcp';
348
+ host?: string;
349
+ port: number;
350
+ backlog?: number;
351
+ }
352
+
311
353
  // Union of all node types
312
354
  export type NodeRecord =
313
355
  | FunctionNodeRecord
@@ -332,6 +374,10 @@ export type NodeRecord =
332
374
  | EventListenerNodeRecord
333
375
  | GuaranteeNodeRecord
334
376
  | PluginNodeRecord
377
+ | OsUnixSocketNodeRecord
378
+ | OsUnixServerNodeRecord
379
+ | NetTcpConnectionNodeRecord
380
+ | NetTcpServerNodeRecord
335
381
  | BaseNodeRecord; // fallback for custom types
336
382
 
337
383
  // === HELPER FUNCTIONS ===
@@ -358,5 +404,5 @@ export function isEndpointType(nodeType: string): boolean {
358
404
  export function isSideEffectType(nodeType: string): boolean {
359
405
  if (nodeType === NODE_TYPE.SIDE_EFFECT) return true;
360
406
  const ns = getNamespace(nodeType);
361
- return ns === 'db' || ns === 'fs' || ns === 'net';
407
+ return ns === 'db' || ns === 'fs' || ns === 'net' || ns === 'os';
362
408
  }
package/src/plugins.ts CHANGED
@@ -4,7 +4,11 @@
4
4
 
5
5
  import type { NodeType, NodeRecord } from './nodes.js';
6
6
  import type { EdgeType, EdgeRecord } from './edges.js';
7
- import type { FieldDeclaration } from './rfdb.js';
7
+ import type { AnyBrandedNode } from './branded.js';
8
+ import type { FieldDeclaration, CommitDelta } from './rfdb.js';
9
+ import type { ResourceRegistry } from './resources.js';
10
+ import type { RoutingRule } from './routing.js';
11
+ import type { InfrastructureConfig } from './infrastructure.js';
8
12
 
9
13
  // === LOG LEVEL ===
10
14
  /**
@@ -48,6 +52,16 @@ export interface PluginMetadata {
48
52
  dependencies?: string[];
49
53
  /** Metadata fields this plugin writes. Used for RFDB server-side indexing. */
50
54
  fields?: FieldDeclaration[];
55
+ /**
56
+ * Package names this analyzer covers (for coverage tracking).
57
+ * Only used by package-specific analyzers.
58
+ * Examples: ['sqlite3'], ['@prisma/client'], ['lodash']
59
+ */
60
+ covers?: string[];
61
+ /** Edge types this plugin reads from the graph (RFD-2). Used for automatic dependency inference. */
62
+ consumes?: EdgeType[];
63
+ /** Edge types this plugin creates/modifies (RFD-2). Used for automatic dependency inference. */
64
+ produces?: EdgeType[];
51
65
  }
52
66
 
53
67
  // === ISSUE SPEC ===
@@ -121,6 +135,13 @@ export interface PluginContext {
121
135
  * - Multi root ("backend"): "backend/src/utils.js->global->FUNCTION->foo"
122
136
  */
123
137
  rootPrefix?: string;
138
+
139
+ /**
140
+ * Resource registry for shared data between plugins (REG-256).
141
+ * Plugins can read/write typed Resources through this registry.
142
+ * Available in all phases. Created by Orchestrator at run start.
143
+ */
144
+ resources?: ResourceRegistry;
124
145
  }
125
146
 
126
147
  // === PLUGIN RESULT ===
@@ -198,6 +219,15 @@ export interface OrchestratorConfig {
198
219
  * Note: node_modules is already excluded by default in JSModuleIndexer.
199
220
  */
200
221
  exclude?: string[];
222
+
223
+ /**
224
+ * Routing rules from config for cross-service URL mapping (REG-256).
225
+ * Passed through to plugins via PluginContext.config.
226
+ */
227
+ routing?: RoutingRule[];
228
+
229
+ /** Infrastructure analysis configuration (USG Phase 1) */
230
+ infrastructure?: InfrastructureConfig;
201
231
  }
202
232
 
203
233
  /**
@@ -224,20 +254,17 @@ export interface ServiceDefinition {
224
254
  * If omitted, auto-detected via resolveSourceEntrypoint() or package.json.main
225
255
  */
226
256
  entryPoint?: string;
227
- }
228
257
 
229
- // === GRAPH BACKEND INTERFACE ===
230
- // Flexible input types for graph operations
231
- export interface InputNode {
232
- id: string;
233
- type?: string;
234
- nodeType?: string;
235
- name?: string;
236
- file?: string;
237
- line?: number;
238
- [key: string]: unknown;
258
+ /**
259
+ * Mark this service as customer-facing (REG-256).
260
+ * Routes in customer-facing services are expected to have frontend consumers.
261
+ * Unconnected routes in customer-facing services raise issue:connectivity warnings.
262
+ * Default: false (no issues for unconnected routes).
263
+ */
264
+ customerFacing?: boolean;
239
265
  }
240
266
 
267
+ // === GRAPH BACKEND INTERFACE ===
241
268
  export interface InputEdge {
242
269
  src: string;
243
270
  dst: string;
@@ -247,9 +274,9 @@ export interface InputEdge {
247
274
 
248
275
  // Minimal interface for graph operations
249
276
  export interface GraphBackend {
250
- addNode(node: InputNode): Promise<void> | void;
277
+ addNode(node: AnyBrandedNode): Promise<void> | void;
251
278
  addEdge(edge: InputEdge): Promise<void> | void;
252
- addNodes(nodes: InputNode[]): Promise<void> | void;
279
+ addNodes(nodes: AnyBrandedNode[]): Promise<void> | void;
253
280
  addEdges(edges: InputEdge[]): Promise<void> | void;
254
281
 
255
282
  getNode(id: string): Promise<NodeRecord | null>;
@@ -284,6 +311,11 @@ export interface GraphBackend {
284
311
 
285
312
  // Schema declaration
286
313
  declareFields?(fields: FieldDeclaration[]): Promise<number>;
314
+
315
+ // Batch operations (RFD-16: CommitBatch protocol)
316
+ beginBatch?(): void;
317
+ commitBatch?(tags?: string[]): Promise<CommitDelta>;
318
+ abortBatch?(): void;
287
319
  }
288
320
 
289
321
  export interface NodeFilter {
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Resource Types — shared typed data containers for inter-plugin communication.
3
+ *
4
+ * Resources are created during a pipeline run and destroyed when the run ends.
5
+ * Multiple plugins can write to a Resource; any plugin can read from it.
6
+ *
7
+ * Unlike graph nodes, Resources are:
8
+ * - Not persisted to RFDB
9
+ * - Not queryable via Datalog
10
+ * - Typed (each Resource has a known interface)
11
+ * - Scoped to a single pipeline run
12
+ *
13
+ * Resources are for structured data that plugins share but that doesn't
14
+ * belong in the code graph (config-derived rules, computed indexes, etc.).
15
+ */
16
+
17
+ /**
18
+ * Unique identifier for a Resource type.
19
+ * Convention: 'domain:name' (e.g., 'routing:map', 'auth:policies').
20
+ */
21
+ export type ResourceId = string;
22
+
23
+ /**
24
+ * Base interface for all Resources.
25
+ */
26
+ export interface Resource {
27
+ /** Unique identifier for this Resource type */
28
+ readonly id: ResourceId;
29
+ }
30
+
31
+ /**
32
+ * Registry for managing Resources during a pipeline run.
33
+ * The Orchestrator creates one ResourceRegistry per run.
34
+ * Plugins access it via PluginContext.
35
+ */
36
+ export interface ResourceRegistry {
37
+ /**
38
+ * Get or create a Resource by ID.
39
+ * If the Resource doesn't exist yet, creates it using the factory.
40
+ * If it already exists, returns the existing instance (factory ignored).
41
+ *
42
+ * @param id - Resource identifier
43
+ * @param factory - Factory function to create the Resource if it doesn't exist
44
+ * @returns The Resource instance (existing or newly created)
45
+ */
46
+ getOrCreate<T extends Resource>(id: ResourceId, factory: () => T): T;
47
+
48
+ /**
49
+ * Get a Resource by ID. Returns undefined if not yet created.
50
+ * Use this when a plugin wants to READ a Resource but should not create it.
51
+ */
52
+ get<T extends Resource>(id: ResourceId): T | undefined;
53
+
54
+ /**
55
+ * Check if a Resource exists.
56
+ */
57
+ has(id: ResourceId): boolean;
58
+ }