@neat.is/types 0.7.5 → 0.7.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.
package/dist/index.cjs CHANGED
@@ -55,6 +55,7 @@ __export(index_exports, {
55
55
  EdgeTypeSchema: () => EdgeTypeSchema,
56
56
  ErrorEventSchema: () => ErrorEventSchema,
57
57
  ExtractionCoverageSchema: () => ExtractionCoverageSchema,
58
+ FieldGuardRuleSchema: () => FieldGuardRuleSchema,
58
59
  FileNodeSchema: () => FileNodeSchema,
59
60
  FrontierNodeSchema: () => FrontierNodeSchema,
60
61
  GraphDiffResultSchema: () => GraphDiffResultSchema,
@@ -101,6 +102,7 @@ __export(index_exports, {
101
102
  SearchMatchSchema: () => SearchMatchSchema,
102
103
  SearchResponseSchema: () => SearchResponseSchema,
103
104
  SerializedGraphSchema: () => SerializedGraphSchema,
105
+ ServerActionNodeSchema: () => ServerActionNodeSchema,
104
106
  ServiceNodeSchema: () => ServiceNodeSchema,
105
107
  SingleProjectResponseSchema: () => SingleProjectResponseSchema,
106
108
  SpanAttributesSchema: () => SpanAttributesSchema,
@@ -137,11 +139,13 @@ __export(index_exports, {
137
139
  parseGrpcMethodId: () => parseGrpcMethodId,
138
140
  parseInfraId: () => parseInfraId,
139
141
  parseRouteId: () => parseRouteId,
142
+ parseServerActionId: () => parseServerActionId,
140
143
  parseServiceId: () => parseServiceId,
141
144
  parseSymbolId: () => parseSymbolId,
142
145
  parseWebsocketChannelId: () => parseWebsocketChannelId,
143
146
  passesExtractedFloor: () => passesExtractedFloor,
144
147
  routeId: () => routeId,
148
+ serverActionId: () => serverActionId,
145
149
  serviceId: () => serviceId,
146
150
  symbolId: () => symbolId,
147
151
  websocketChannelId: () => websocketChannelId
@@ -252,7 +256,22 @@ var NodeType = {
252
256
  // file (observed-first edges, one grain finer than §4 file grain). The node is
253
257
  // language-neutral; the per-language tree-sitter extractor is the adapter. See
254
258
  // docs/contracts/static-extraction.md and docs/contracts/file-awareness.md §1.
255
- SymbolNode: "SymbolNode"
259
+ SymbolNode: "SymbolNode",
260
+ // A Next.js Server Action at (service, module, exportName) granularity
261
+ // (ADR-168). A Server Action is the RPC boundary of an App Router app: the
262
+ // client posts to it, Next serialises the call to an opaque `Next-Action`
263
+ // hash, and it runs on the server. At HTTP grain the whole surface collapses
264
+ // onto one POST edge — like a GraphQL operation — so this node recovers the
265
+ // per-action topology the client actually names. It is EXTRACTED-first: the
266
+ // static extractor mints one per exported action from a `"use server"`
267
+ // directive (module-level or in-body) and the file owns it through a
268
+ // `file ──CONTAINS──▶ action` edge; a client reference to the imported action
269
+ // binding lands a `file ──CALLS──▶ action` edge, so the client→action call
270
+ // path is a real edge the reasoning core walks like any other. OBSERVED
271
+ // fusion is deferred (the `Next-Action` hash carries no action name), the
272
+ // same posture GraphQLOperationNode took before its static extractor. See
273
+ // docs/contracts/static-extraction.md and docs/contracts/file-awareness.md.
274
+ ServerActionNode: "ServerActionNode"
256
275
  };
257
276
  var NodeTypeSchema = import_zod.z.enum([
258
277
  NodeType.ServiceNode,
@@ -265,7 +284,8 @@ var NodeTypeSchema = import_zod.z.enum([
265
284
  NodeType.GraphQLOperationNode,
266
285
  NodeType.GrpcMethodNode,
267
286
  NodeType.WebSocketChannelNode,
268
- NodeType.SymbolNode
287
+ NodeType.SymbolNode,
288
+ NodeType.ServerActionNode
269
289
  ]);
270
290
 
271
291
  // src/nodes.ts
@@ -436,7 +456,15 @@ var ConfigNodeSchema = import_zod3.z.object({
436
456
  var ColumnAttrSchema = import_zod3.z.object({
437
457
  name: import_zod3.z.string(),
438
458
  provenances: import_zod3.z.array(ProvenanceSchema),
439
- confidence: import_zod3.z.number().min(0).max(1)
459
+ confidence: import_zod3.z.number().min(0).max(1),
460
+ // Which SDK wrote this field, for a `firestore-collection` node (ADR-167): a
461
+ // deduped set, the write-side analog of `provenances`. `client` =
462
+ // firebase/firestore (governed by security rules), `admin` =
463
+ // firebase-admin/firestore (bypasses rules entirely). This is the seam the
464
+ // field-guard policy (ADR-169) joins on — client-written fields must be guarded
465
+ // — and is absent on a non-Firestore column. Optional growth, no version step
466
+ // (`kind` is an open string); folded by `foldSdkWrites`, never `foldColumns`.
467
+ sdkWrites: import_zod3.z.array(import_zod3.z.enum(["client", "admin"])).optional()
440
468
  });
441
469
  var InfraNodeSchema = import_zod3.z.object({
442
470
  id: import_zod3.z.string(),
@@ -449,7 +477,15 @@ var InfraNodeSchema = import_zod3.z.object({
449
477
  // Absent on a non-table InfraNode (a project node, a queue, a route). Optional
450
478
  // schema growth (ADR-031); ADR-157 stamps the snapshot version because the field
451
479
  // records a new grain the graph can now carry. See docs/contracts/schema.md.
452
- columns: import_zod3.z.array(ColumnAttrSchema).optional()
480
+ columns: import_zod3.z.array(ColumnAttrSchema).optional(),
481
+ // Guard set folded from a checked-in declared policy artifact (ADR-169): for a
482
+ // `firestore-collection` node, the fields `firestore.rules` explicitly names on
483
+ // the client write path, read by the standalone rules producer. The
484
+ // `field-guard` policy asserts every client-written column appears here. Absent
485
+ // ⇒ the collection's guard is indeterminate ⇒ the check stays silent. Optional
486
+ // growth (ADR-031); no version step — it only appears on nodes a post-ADR-169
487
+ // pass folds it onto.
488
+ guardedFields: import_zod3.z.array(import_zod3.z.string()).optional()
453
489
  });
454
490
  var FrontierNodeSchema = import_zod3.z.object({
455
491
  id: import_zod3.z.string(),
@@ -542,6 +578,17 @@ var SymbolNodeSchema = import_zod3.z.object({
542
578
  relPath: import_zod3.z.string(),
543
579
  discoveredVia: DiscoveredViaSchema.optional()
544
580
  });
581
+ var ServerActionNodeSchema = import_zod3.z.object({
582
+ id: import_zod3.z.string(),
583
+ type: import_zod3.z.literal(NodeType.ServerActionNode),
584
+ name: import_zod3.z.string(),
585
+ service: import_zod3.z.string(),
586
+ module: import_zod3.z.string(),
587
+ exportName: import_zod3.z.string(),
588
+ path: import_zod3.z.string().optional(),
589
+ line: import_zod3.z.number().int().nonnegative().optional(),
590
+ discoveredVia: DiscoveredViaSchema.optional()
591
+ });
545
592
  var GraphNodeSchema = import_zod3.z.discriminatedUnion("type", [
546
593
  ServiceNodeSchema,
547
594
  DatabaseNodeSchema,
@@ -553,7 +600,8 @@ var GraphNodeSchema = import_zod3.z.discriminatedUnion("type", [
553
600
  GraphQLOperationNodeSchema,
554
601
  GrpcMethodNodeSchema,
555
602
  WebSocketChannelNodeSchema,
556
- SymbolNodeSchema
603
+ SymbolNodeSchema,
604
+ ServerActionNodeSchema
557
605
  ]);
558
606
 
559
607
  // src/events.ts
@@ -706,6 +754,7 @@ var GRAPHQL_OP_PREFIX = "graphql:";
706
754
  var GRPC_METHOD_PREFIX = "grpc:";
707
755
  var WEBSOCKET_CHANNEL_PREFIX = "ws:";
708
756
  var SYMBOL_PREFIX = "symbol:";
757
+ var SERVER_ACTION_PREFIX = "action:";
709
758
  var ENV_UNKNOWN = "unknown";
710
759
  function serviceId(name, env) {
711
760
  if (env === void 0 || env === ENV_UNKNOWN) return `${SERVICE_PREFIX}${name}`;
@@ -853,6 +902,23 @@ function parseSymbolId(id) {
853
902
  if (qualname.length === 0) return null;
854
903
  return { service, relPath, qualname, ...disambiguator !== void 0 ? { disambiguator } : {} };
855
904
  }
905
+ function serverActionId(service, module2, exportName) {
906
+ return `${SERVER_ACTION_PREFIX}${service}:${module2}#${exportName}`;
907
+ }
908
+ function parseServerActionId(id) {
909
+ if (!id.startsWith(SERVER_ACTION_PREFIX)) return null;
910
+ const rest = id.slice(SERVER_ACTION_PREFIX.length);
911
+ const colon = rest.indexOf(":");
912
+ if (colon === -1) return null;
913
+ const service = rest.slice(0, colon);
914
+ const tail = rest.slice(colon + 1);
915
+ const hash = tail.lastIndexOf("#");
916
+ if (hash === -1) return null;
917
+ const module2 = tail.slice(0, hash);
918
+ const exportName = tail.slice(hash + 1);
919
+ if (service.length === 0 || module2.length === 0 || exportName.length === 0) return null;
920
+ return { service, module: module2, exportName };
921
+ }
856
922
  var EDGE_ARROW = "->";
857
923
  function extractedEdgeId(source, target, type) {
858
924
  return `${type}:${source}${EDGE_ARROW}${target}`;
@@ -939,12 +1005,29 @@ var BlastRadiusRuleSchema = import_zod6.z.object({
939
1005
  // default (10) when omitted.
940
1006
  depth: import_zod6.z.number().int().positive().optional()
941
1007
  });
1008
+ var FieldGuardRuleSchema = import_zod6.z.object({
1009
+ type: import_zod6.z.literal("field-guard"),
1010
+ // Node type the rule governs. InfraNode for the Firestore instance.
1011
+ nodeType: NodeTypeSchema,
1012
+ // Optional narrowing on InfraNode's free-string `kind` sub-type, so the rule
1013
+ // applies to `firestore-collection` nodes without governing every InfraNode.
1014
+ nodeKind: import_zod6.z.string().optional(),
1015
+ // Set A — the named selector the evaluator resolves into the "must be covered"
1016
+ // set. 'client-written-columns' reads ColumnAttr whose sdkWrites includes
1017
+ // 'client'. A new instance adds a value here plus a resolver branch.
1018
+ subjectSet: import_zod6.z.enum(["client-written-columns"]),
1019
+ // Set B — the covering set: the node attribute (a string[]) whose members must
1020
+ // include all of set A. 'guardedFields' for Firestore. Absent ⇒ indeterminate
1021
+ // ⇒ silent.
1022
+ guardSet: import_zod6.z.string()
1023
+ });
942
1024
  var PolicyRuleSchema = import_zod6.z.discriminatedUnion("type", [
943
1025
  StructuralRuleSchema,
944
1026
  CompatibilityRuleSchema,
945
1027
  ProvenanceRuleSchema,
946
1028
  OwnershipRuleSchema,
947
- BlastRadiusRuleSchema
1029
+ BlastRadiusRuleSchema,
1030
+ FieldGuardRuleSchema
948
1031
  ]);
949
1032
  var PolicySchema = import_zod6.z.object({
950
1033
  // Unique within the file. Duplicates fail PolicyFileSchema.parse.
@@ -1003,7 +1086,7 @@ var ApplicablePolicySchema = import_zod6.z.object({
1003
1086
  // from policy.onViolation or the severity default. Shown for awareness only;
1004
1087
  // the soft guardrail never acts on it.
1005
1088
  onViolation: PolicyActionSchema,
1006
- ruleType: import_zod6.z.enum(["structural", "compatibility", "provenance", "ownership", "blast-radius"]),
1089
+ ruleType: import_zod6.z.enum(["structural", "compatibility", "provenance", "ownership", "blast-radius", "field-guard"]),
1007
1090
  match: import_zod6.z.enum(["subject", "region"]),
1008
1091
  // Human-readable reason the policy applies here — rides into agent context.
1009
1092
  reason: import_zod6.z.string().min(1)
@@ -1022,7 +1105,7 @@ var PolicyViolationSchema = import_zod6.z.object({
1022
1105
  // Resolved at evaluation time — either the explicit policy.onViolation or
1023
1106
  // the severity-derived default per ADR-044.
1024
1107
  onViolation: PolicyActionSchema,
1025
- ruleType: import_zod6.z.enum(["structural", "compatibility", "provenance", "ownership", "blast-radius"]),
1108
+ ruleType: import_zod6.z.enum(["structural", "compatibility", "provenance", "ownership", "blast-radius", "field-guard"]),
1026
1109
  subject: import_zod6.z.object({
1027
1110
  nodeId: import_zod6.z.string().optional(),
1028
1111
  edgeId: import_zod6.z.string().optional(),
@@ -1371,6 +1454,7 @@ function passesExtractedFloor(confidence) {
1371
1454
  EdgeTypeSchema,
1372
1455
  ErrorEventSchema,
1373
1456
  ExtractionCoverageSchema,
1457
+ FieldGuardRuleSchema,
1374
1458
  FileNodeSchema,
1375
1459
  FrontierNodeSchema,
1376
1460
  GraphDiffResultSchema,
@@ -1417,6 +1501,7 @@ function passesExtractedFloor(confidence) {
1417
1501
  SearchMatchSchema,
1418
1502
  SearchResponseSchema,
1419
1503
  SerializedGraphSchema,
1504
+ ServerActionNodeSchema,
1420
1505
  ServiceNodeSchema,
1421
1506
  SingleProjectResponseSchema,
1422
1507
  SpanAttributesSchema,
@@ -1453,11 +1538,13 @@ function passesExtractedFloor(confidence) {
1453
1538
  parseGrpcMethodId,
1454
1539
  parseInfraId,
1455
1540
  parseRouteId,
1541
+ parseServerActionId,
1456
1542
  parseServiceId,
1457
1543
  parseSymbolId,
1458
1544
  parseWebsocketChannelId,
1459
1545
  passesExtractedFloor,
1460
1546
  routeId,
1547
+ serverActionId,
1461
1548
  serviceId,
1462
1549
  symbolId,
1463
1550
  websocketChannelId