@neat.is/types 0.7.4 → 0.7.6

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.
package/dist/index.js CHANGED
@@ -31,7 +31,17 @@ var EdgeType = {
31
31
  // fuzzy-matched. A parent that resolves to nothing (external package,
32
32
  // re-export chain, an interface, which is not a SymbolNode) emits no edge.
33
33
  INHERITS: "INHERITS",
34
- IMPLEMENTS: "IMPLEMENTS"
34
+ IMPLEMENTS: "IMPLEMENTS",
35
+ // Static foreign-key reference between two table InfraNodes (ADR-161).
36
+ // `infra:sql-table:<child> ──REFERENCES──▶ infra:sql-table:<parent>` records
37
+ // that the child table declares a foreign key into the parent — the data-axis
38
+ // sibling of INHERITS/IMPLEMENTS. Both endpoints resolve to the DATABASE table
39
+ // name via `infraId('sql-table', name)` — the same node the column/table
40
+ // extractors and OTLP already target — reproduced verbatim per ORM, so the FK
41
+ // edge lands on the fused table node rather than a code-model twin. EXTRACTED,
42
+ // minted only when the parent resolves to a real declared table without
43
+ // guessing; a computed/unresolved reference emits no edge.
44
+ REFERENCES: "REFERENCES"
35
45
  };
36
46
  var NodeType = {
37
47
  ServiceNode: "ServiceNode",
@@ -92,7 +102,22 @@ var NodeType = {
92
102
  // file (observed-first edges, one grain finer than §4 file grain). The node is
93
103
  // language-neutral; the per-language tree-sitter extractor is the adapter. See
94
104
  // docs/contracts/static-extraction.md and docs/contracts/file-awareness.md §1.
95
- SymbolNode: "SymbolNode"
105
+ SymbolNode: "SymbolNode",
106
+ // A Next.js Server Action at (service, module, exportName) granularity
107
+ // (ADR-168). A Server Action is the RPC boundary of an App Router app: the
108
+ // client posts to it, Next serialises the call to an opaque `Next-Action`
109
+ // hash, and it runs on the server. At HTTP grain the whole surface collapses
110
+ // onto one POST edge — like a GraphQL operation — so this node recovers the
111
+ // per-action topology the client actually names. It is EXTRACTED-first: the
112
+ // static extractor mints one per exported action from a `"use server"`
113
+ // directive (module-level or in-body) and the file owns it through a
114
+ // `file ──CONTAINS──▶ action` edge; a client reference to the imported action
115
+ // binding lands a `file ──CALLS──▶ action` edge, so the client→action call
116
+ // path is a real edge the reasoning core walks like any other. OBSERVED
117
+ // fusion is deferred (the `Next-Action` hash carries no action name), the
118
+ // same posture GraphQLOperationNode took before its static extractor. See
119
+ // docs/contracts/static-extraction.md and docs/contracts/file-awareness.md.
120
+ ServerActionNode: "ServerActionNode"
96
121
  };
97
122
  var NodeTypeSchema = z.enum([
98
123
  NodeType.ServiceNode,
@@ -105,7 +130,8 @@ var NodeTypeSchema = z.enum([
105
130
  NodeType.GraphQLOperationNode,
106
131
  NodeType.GrpcMethodNode,
107
132
  NodeType.WebSocketChannelNode,
108
- NodeType.SymbolNode
133
+ NodeType.SymbolNode,
134
+ NodeType.ServerActionNode
109
135
  ]);
110
136
 
111
137
  // src/nodes.ts
@@ -130,7 +156,8 @@ var EdgeTypeSchema = z2.enum([
130
156
  EdgeType.CONTAINS,
131
157
  EdgeType.IMPORTS,
132
158
  EdgeType.INHERITS,
133
- EdgeType.IMPLEMENTS
159
+ EdgeType.IMPLEMENTS,
160
+ EdgeType.REFERENCES
134
161
  ]);
135
162
  var EdgeEvidenceSchema = z2.object({
136
163
  file: z2.string(),
@@ -275,7 +302,15 @@ var ConfigNodeSchema = z3.object({
275
302
  var ColumnAttrSchema = z3.object({
276
303
  name: z3.string(),
277
304
  provenances: z3.array(ProvenanceSchema),
278
- confidence: z3.number().min(0).max(1)
305
+ confidence: z3.number().min(0).max(1),
306
+ // Which SDK wrote this field, for a `firestore-collection` node (ADR-167): a
307
+ // deduped set, the write-side analog of `provenances`. `client` =
308
+ // firebase/firestore (governed by security rules), `admin` =
309
+ // firebase-admin/firestore (bypasses rules entirely). This is the seam the
310
+ // field-guard policy (ADR-169) joins on — client-written fields must be guarded
311
+ // — and is absent on a non-Firestore column. Optional growth, no version step
312
+ // (`kind` is an open string); folded by `foldSdkWrites`, never `foldColumns`.
313
+ sdkWrites: z3.array(z3.enum(["client", "admin"])).optional()
279
314
  });
280
315
  var InfraNodeSchema = z3.object({
281
316
  id: z3.string(),
@@ -288,7 +323,15 @@ var InfraNodeSchema = z3.object({
288
323
  // Absent on a non-table InfraNode (a project node, a queue, a route). Optional
289
324
  // schema growth (ADR-031); ADR-157 stamps the snapshot version because the field
290
325
  // records a new grain the graph can now carry. See docs/contracts/schema.md.
291
- columns: z3.array(ColumnAttrSchema).optional()
326
+ columns: z3.array(ColumnAttrSchema).optional(),
327
+ // Guard set folded from a checked-in declared policy artifact (ADR-169): for a
328
+ // `firestore-collection` node, the fields `firestore.rules` explicitly names on
329
+ // the client write path, read by the standalone rules producer. The
330
+ // `field-guard` policy asserts every client-written column appears here. Absent
331
+ // ⇒ the collection's guard is indeterminate ⇒ the check stays silent. Optional
332
+ // growth (ADR-031); no version step — it only appears on nodes a post-ADR-169
333
+ // pass folds it onto.
334
+ guardedFields: z3.array(z3.string()).optional()
292
335
  });
293
336
  var FrontierNodeSchema = z3.object({
294
337
  id: z3.string(),
@@ -381,6 +424,17 @@ var SymbolNodeSchema = z3.object({
381
424
  relPath: z3.string(),
382
425
  discoveredVia: DiscoveredViaSchema.optional()
383
426
  });
427
+ var ServerActionNodeSchema = z3.object({
428
+ id: z3.string(),
429
+ type: z3.literal(NodeType.ServerActionNode),
430
+ name: z3.string(),
431
+ service: z3.string(),
432
+ module: z3.string(),
433
+ exportName: z3.string(),
434
+ path: z3.string().optional(),
435
+ line: z3.number().int().nonnegative().optional(),
436
+ discoveredVia: DiscoveredViaSchema.optional()
437
+ });
384
438
  var GraphNodeSchema = z3.discriminatedUnion("type", [
385
439
  ServiceNodeSchema,
386
440
  DatabaseNodeSchema,
@@ -392,7 +446,8 @@ var GraphNodeSchema = z3.discriminatedUnion("type", [
392
446
  GraphQLOperationNodeSchema,
393
447
  GrpcMethodNodeSchema,
394
448
  WebSocketChannelNodeSchema,
395
- SymbolNodeSchema
449
+ SymbolNodeSchema,
450
+ ServerActionNodeSchema
396
451
  ]);
397
452
 
398
453
  // src/events.ts
@@ -545,6 +600,7 @@ var GRAPHQL_OP_PREFIX = "graphql:";
545
600
  var GRPC_METHOD_PREFIX = "grpc:";
546
601
  var WEBSOCKET_CHANNEL_PREFIX = "ws:";
547
602
  var SYMBOL_PREFIX = "symbol:";
603
+ var SERVER_ACTION_PREFIX = "action:";
548
604
  var ENV_UNKNOWN = "unknown";
549
605
  function serviceId(name, env) {
550
606
  if (env === void 0 || env === ENV_UNKNOWN) return `${SERVICE_PREFIX}${name}`;
@@ -692,6 +748,23 @@ function parseSymbolId(id) {
692
748
  if (qualname.length === 0) return null;
693
749
  return { service, relPath, qualname, ...disambiguator !== void 0 ? { disambiguator } : {} };
694
750
  }
751
+ function serverActionId(service, module, exportName) {
752
+ return `${SERVER_ACTION_PREFIX}${service}:${module}#${exportName}`;
753
+ }
754
+ function parseServerActionId(id) {
755
+ if (!id.startsWith(SERVER_ACTION_PREFIX)) return null;
756
+ const rest = id.slice(SERVER_ACTION_PREFIX.length);
757
+ const colon = rest.indexOf(":");
758
+ if (colon === -1) return null;
759
+ const service = rest.slice(0, colon);
760
+ const tail = rest.slice(colon + 1);
761
+ const hash = tail.lastIndexOf("#");
762
+ if (hash === -1) return null;
763
+ const module = tail.slice(0, hash);
764
+ const exportName = tail.slice(hash + 1);
765
+ if (service.length === 0 || module.length === 0 || exportName.length === 0) return null;
766
+ return { service, module, exportName };
767
+ }
695
768
  var EDGE_ARROW = "->";
696
769
  function extractedEdgeId(source, target, type) {
697
770
  return `${type}:${source}${EDGE_ARROW}${target}`;
@@ -778,12 +851,29 @@ var BlastRadiusRuleSchema = z6.object({
778
851
  // default (10) when omitted.
779
852
  depth: z6.number().int().positive().optional()
780
853
  });
854
+ var FieldGuardRuleSchema = z6.object({
855
+ type: z6.literal("field-guard"),
856
+ // Node type the rule governs. InfraNode for the Firestore instance.
857
+ nodeType: NodeTypeSchema,
858
+ // Optional narrowing on InfraNode's free-string `kind` sub-type, so the rule
859
+ // applies to `firestore-collection` nodes without governing every InfraNode.
860
+ nodeKind: z6.string().optional(),
861
+ // Set A — the named selector the evaluator resolves into the "must be covered"
862
+ // set. 'client-written-columns' reads ColumnAttr whose sdkWrites includes
863
+ // 'client'. A new instance adds a value here plus a resolver branch.
864
+ subjectSet: z6.enum(["client-written-columns"]),
865
+ // Set B — the covering set: the node attribute (a string[]) whose members must
866
+ // include all of set A. 'guardedFields' for Firestore. Absent ⇒ indeterminate
867
+ // ⇒ silent.
868
+ guardSet: z6.string()
869
+ });
781
870
  var PolicyRuleSchema = z6.discriminatedUnion("type", [
782
871
  StructuralRuleSchema,
783
872
  CompatibilityRuleSchema,
784
873
  ProvenanceRuleSchema,
785
874
  OwnershipRuleSchema,
786
- BlastRadiusRuleSchema
875
+ BlastRadiusRuleSchema,
876
+ FieldGuardRuleSchema
787
877
  ]);
788
878
  var PolicySchema = z6.object({
789
879
  // Unique within the file. Duplicates fail PolicyFileSchema.parse.
@@ -842,7 +932,7 @@ var ApplicablePolicySchema = z6.object({
842
932
  // from policy.onViolation or the severity default. Shown for awareness only;
843
933
  // the soft guardrail never acts on it.
844
934
  onViolation: PolicyActionSchema,
845
- ruleType: z6.enum(["structural", "compatibility", "provenance", "ownership", "blast-radius"]),
935
+ ruleType: z6.enum(["structural", "compatibility", "provenance", "ownership", "blast-radius", "field-guard"]),
846
936
  match: z6.enum(["subject", "region"]),
847
937
  // Human-readable reason the policy applies here — rides into agent context.
848
938
  reason: z6.string().min(1)
@@ -861,7 +951,7 @@ var PolicyViolationSchema = z6.object({
861
951
  // Resolved at evaluation time — either the explicit policy.onViolation or
862
952
  // the severity-derived default per ADR-044.
863
953
  onViolation: PolicyActionSchema,
864
- ruleType: z6.enum(["structural", "compatibility", "provenance", "ownership", "blast-radius"]),
954
+ ruleType: z6.enum(["structural", "compatibility", "provenance", "ownership", "blast-radius", "field-guard"]),
865
955
  subject: z6.object({
866
956
  nodeId: z6.string().optional(),
867
957
  edgeId: z6.string().optional(),
@@ -1209,6 +1299,7 @@ export {
1209
1299
  EdgeTypeSchema,
1210
1300
  ErrorEventSchema,
1211
1301
  ExtractionCoverageSchema,
1302
+ FieldGuardRuleSchema,
1212
1303
  FileNodeSchema,
1213
1304
  FrontierNodeSchema,
1214
1305
  GraphDiffResultSchema,
@@ -1255,6 +1346,7 @@ export {
1255
1346
  SearchMatchSchema,
1256
1347
  SearchResponseSchema,
1257
1348
  SerializedGraphSchema,
1349
+ ServerActionNodeSchema,
1258
1350
  ServiceNodeSchema,
1259
1351
  SingleProjectResponseSchema,
1260
1352
  SpanAttributesSchema,
@@ -1291,11 +1383,13 @@ export {
1291
1383
  parseGrpcMethodId,
1292
1384
  parseInfraId,
1293
1385
  parseRouteId,
1386
+ parseServerActionId,
1294
1387
  parseServiceId,
1295
1388
  parseSymbolId,
1296
1389
  parseWebsocketChannelId,
1297
1390
  passesExtractedFloor,
1298
1391
  routeId,
1392
+ serverActionId,
1299
1393
  serviceId,
1300
1394
  symbolId,
1301
1395
  websocketChannelId