@synapsor/runner 1.5.4 → 1.6.0

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 (42) hide show
  1. package/CHANGELOG.md +40 -2
  2. package/README.md +117 -124
  3. package/dist/authoring.mjs +405 -9
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/local-ui.d.ts +2 -0
  6. package/dist/local-ui.d.ts.map +1 -1
  7. package/dist/runner.mjs +31036 -27581
  8. package/dist/runtime.mjs +10264 -8543
  9. package/docs/README.md +14 -6
  10. package/docs/aggregate-reads.md +22 -0
  11. package/docs/auto-boundary-and-scoped-explore.md +338 -0
  12. package/docs/capability-authoring.md +30 -0
  13. package/docs/conformance.md +16 -0
  14. package/docs/current-scope.md +55 -28
  15. package/docs/cursor-plugin.md +20 -3
  16. package/docs/dsl-reference.md +78 -0
  17. package/docs/getting-started-own-database.md +39 -35
  18. package/docs/limitations.md +24 -7
  19. package/docs/release-notes.md +37 -4
  20. package/docs/schema-api-candidates.md +28 -1
  21. package/docs/troubleshooting-first-run.md +98 -0
  22. package/examples/auto-boundary-churn/README.md +23 -0
  23. package/examples/auto-boundary-churn/app/page.tsx +8 -0
  24. package/examples/auto-boundary-churn/docker-compose.yml +16 -0
  25. package/examples/auto-boundary-churn/package.json +18 -0
  26. package/examples/auto-boundary-churn/prisma/schema.prisma +36 -0
  27. package/examples/auto-boundary-churn/seed/postgres.sql +126 -0
  28. package/fixtures/compatibility/published-1.5.4/manifest.json +76 -0
  29. package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/aggregate-read.synapsor.sql +21 -0
  30. package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/billing-late-fee.synapsor.sql +56 -0
  31. package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/bounded-set-multi-term.synapsor.sql +30 -0
  32. package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/principal-row-scope.synapsor.sql +23 -0
  33. package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/aggregate-read/contract.json +119 -0
  34. package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/approval-quorum/contract.json +44 -0
  35. package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/bounded-set-threats/contract.json +115 -0
  36. package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/principal-row-scope/contract.json +78 -0
  37. package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/proposal-capability/contract.json +101 -0
  38. package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/reversible-change-sets/contract.json +98 -0
  39. package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/valid/basic-read.contract.json +60 -0
  40. package/llms.txt +37 -0
  41. package/package.json +7 -4
  42. package/schemas/synapsor.runner.schema.json +18 -1
@@ -1,7 +1,7 @@
1
- // node_modules/.pnpm/@synapsor+spec@1.4.2/node_modules/@synapsor/spec/dist/version.js
1
+ // packages/spec/dist/version.js
2
2
  var SPEC_VERSION = "0.1";
3
3
 
4
- // node_modules/.pnpm/@synapsor+spec@1.4.2/node_modules/@synapsor/spec/dist/errors.js
4
+ // packages/spec/dist/errors.js
5
5
  var SynapsorSpecValidationError = class extends Error {
6
6
  issues;
7
7
  constructor(issues) {
@@ -12,7 +12,7 @@ ${issues.map((issue) => `${issue.path} ${issue.code}: ${issue.message}`).join("\
12
12
  }
13
13
  };
14
14
 
15
- // node_modules/.pnpm/@synapsor+spec@1.4.2/node_modules/@synapsor/spec/dist/validate.js
15
+ // packages/spec/dist/validate.js
16
16
  var TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
17
17
  "spec_version",
18
18
  "kind",
@@ -32,7 +32,7 @@ var METADATA_KEYS = /* @__PURE__ */ new Set(["name", "description", "version", "
32
32
  var RESOURCE_KEYS = /* @__PURE__ */ new Set(["name", "engine", "schema", "table", "type", "primary_key", "tenant_key", "conflict_key", "single_tenant_dev"]);
33
33
  var CONTEXT_KEYS = /* @__PURE__ */ new Set(["name", "description", "bindings", "tenant_binding", "principal_binding"]);
34
34
  var BINDING_KEYS = /* @__PURE__ */ new Set(["name", "source", "key", "required"]);
35
- var CAPABILITY_KEYS = /* @__PURE__ */ new Set(["name", "description", "returns_hint", "kind", "context", "source", "subject", "args", "lookup", "visible_fields", "kept_out_fields", "evidence", "max_rows", "proposal", "aggregate"]);
35
+ var CAPABILITY_KEYS = /* @__PURE__ */ new Set(["name", "description", "returns_hint", "kind", "context", "source", "subject", "args", "lookup", "visible_fields", "kept_out_fields", "evidence", "max_rows", "proposal", "aggregate", "protected_read"]);
36
36
  var SUBJECT_KEYS = /* @__PURE__ */ new Set(["resource", "schema", "table", "primary_key", "tenant_key", "principal_scope_key", "conflict_key", "single_tenant_dev"]);
37
37
  var ARG_KEYS = /* @__PURE__ */ new Set(["type", "description", "required", "max_length", "minimum", "maximum", "enum", "max_items", "fields"]);
38
38
  var LOOKUP_KEYS = /* @__PURE__ */ new Set(["id_from_arg"]);
@@ -55,6 +55,59 @@ var APPROVAL_KEYS = /* @__PURE__ */ new Set(["mode", "required_role", "required_
55
55
  var WRITEBACK_KEYS = /* @__PURE__ */ new Set(["mode", "executor", "idempotency_key"]);
56
56
  var REVERSIBILITY_KEYS = /* @__PURE__ */ new Set(["mode"]);
57
57
  var AGGREGATE_READ_KEYS = /* @__PURE__ */ new Set(["function", "count_mode", "column", "selection", "minimum_group_size"]);
58
+ var PROTECTED_READ_KEYS = /* @__PURE__ */ new Set([
59
+ "version",
60
+ "mode",
61
+ "boundary_digest",
62
+ "generation_lock_fingerprint",
63
+ "predicates",
64
+ "relationship",
65
+ "row_order_by",
66
+ "aggregate",
67
+ "limits"
68
+ ]);
69
+ var PROTECTED_VALUE_KEYS = /* @__PURE__ */ new Set(["fixed", "from_arg"]);
70
+ var PROTECTED_PREDICATE_KEYS = /* @__PURE__ */ new Set(["field", "relationship", "operator", "value", "values"]);
71
+ var PROTECTED_RELATIONSHIP_KEYS = /* @__PURE__ */ new Set([
72
+ "name",
73
+ "schema",
74
+ "table",
75
+ "primary_key",
76
+ "tenant_key",
77
+ "principal_scope_key",
78
+ "local_key",
79
+ "target_key",
80
+ "cardinality",
81
+ "max_fan_out"
82
+ ]);
83
+ var PROTECTED_ROW_ORDER_KEYS = /* @__PURE__ */ new Set(["field", "direction"]);
84
+ var PROTECTED_AGGREGATE_KEYS = /* @__PURE__ */ new Set([
85
+ "counted_entity",
86
+ "measures",
87
+ "dimensions",
88
+ "time_bucket",
89
+ "comparison",
90
+ "order_by",
91
+ "top_n",
92
+ "minimum_group_size"
93
+ ]);
94
+ var PROTECTED_MEASURE_KEYS = /* @__PURE__ */ new Set(["name", "function", "field", "relationship"]);
95
+ var PROTECTED_DIMENSION_KEYS = /* @__PURE__ */ new Set(["name", "field", "relationship"]);
96
+ var PROTECTED_TIME_BUCKET_KEYS = /* @__PURE__ */ new Set(["name", "field", "bucket", "relationship"]);
97
+ var PROTECTED_COMPARISON_KEYS = /* @__PURE__ */ new Set(["field", "relationship", "ranges"]);
98
+ var PROTECTED_RANGE_KEYS = /* @__PURE__ */ new Set(["start", "end"]);
99
+ var PROTECTED_AGGREGATE_ORDER_KEYS = /* @__PURE__ */ new Set(["kind", "measure", "direction"]);
100
+ var PROTECTED_LIMIT_KEYS = /* @__PURE__ */ new Set([
101
+ "max_rows",
102
+ "max_groups",
103
+ "max_response_cells",
104
+ "max_response_bytes",
105
+ "statement_timeout_ms",
106
+ "max_queries_per_session",
107
+ "max_extracted_cells_per_session",
108
+ "max_differencing_queries",
109
+ "rate_limit_per_minute"
110
+ ]);
58
111
  var WORKFLOW_KEYS = /* @__PURE__ */ new Set(["name", "description", "context", "allowed_capabilities", "required_evidence", "approval", "settlement", "replay"]);
59
112
  var POLICY_KEYS = /* @__PURE__ */ new Set(["name", "kind", "mode", "rules", "limits"]);
60
113
  var APPROVAL_POLICY_LIMIT_KEYS = /* @__PURE__ */ new Set(["kind", "max", "period", "field", "scope"]);
@@ -242,7 +295,8 @@ function validateCapabilities(value, contextNames, resourceNames, errors, warnin
242
295
  if (!isNonEmptyString(capability.context) || !contextNames.has(capability.context))
243
296
  errors.push({ path: `${path}.context`, code: "UNKNOWN_CONTEXT", message: "capability.context must reference a declared context." });
244
297
  validateSubject(capability.subject, `${path}.subject`, resourceNames, errors, warnings);
245
- validateArgs(capability.args, `${path}.args`, errors, capability.kind === "aggregate_read");
298
+ const hasProtectedRead = capability.protected_read !== void 0;
299
+ validateArgs(capability.args, `${path}.args`, errors, capability.kind === "aggregate_read" || hasProtectedRead);
246
300
  if (capability.lookup !== void 0)
247
301
  validateLookup(capability.lookup, `${path}.lookup`, capability.args, errors);
248
302
  validateFieldList(capability.visible_fields, `${path}.visible_fields`, "VISIBLE_FIELDS_REQUIRED", errors, capability.kind === "aggregate_read");
@@ -259,10 +313,16 @@ function validateCapabilities(value, contextNames, resourceNames, errors, warnin
259
313
  }
260
314
  if (capability.kind !== "proposal" && capability.proposal !== void 0)
261
315
  errors.push({ path: `${path}.proposal`, code: "PROPOSAL_ONLY_FOR_PROPOSAL_KIND", message: "proposal is only valid for proposal capabilities." });
262
- if (capability.kind === "aggregate_read")
263
- validateAggregateRead(capability, path, errors);
264
- else if (capability.aggregate !== void 0)
316
+ if (hasProtectedRead)
317
+ validateProtectedRead(capability, path, errors);
318
+ if (capability.kind === "aggregate_read") {
319
+ if (!hasProtectedRead)
320
+ validateAggregateRead(capability, path, errors);
321
+ else if (capability.aggregate !== void 0)
322
+ errors.push({ path: `${path}.aggregate`, code: "LEGACY_AGGREGATE_WITH_PROTECTED_READ", message: "protected aggregate reads use protected_read.aggregate and must not also declare the legacy scalar aggregate field." });
323
+ } else if (capability.aggregate !== void 0) {
265
324
  errors.push({ path: `${path}.aggregate`, code: "AGGREGATE_ONLY_FOR_AGGREGATE_READ", message: "aggregate is valid only for aggregate_read capabilities." });
325
+ }
266
326
  });
267
327
  return names;
268
328
  }
@@ -457,6 +517,339 @@ function validateArgs(value, path, errors, allowEmpty = false) {
457
517
  }
458
518
  }
459
519
  }
520
+ function validateProtectedRead(capability, path, errors) {
521
+ const protectedRead = capability.protected_read;
522
+ if (!isRecord(protectedRead)) {
523
+ errors.push({ path: `${path}.protected_read`, code: "PROTECTED_READ_NOT_OBJECT", message: "protected_read must be a reviewed authority object." });
524
+ return;
525
+ }
526
+ checkUnknownKeys(protectedRead, PROTECTED_READ_KEYS, `${path}.protected_read`, errors);
527
+ if (capability.kind !== "read" && capability.kind !== "aggregate_read") {
528
+ errors.push({ path: `${path}.protected_read`, code: "PROTECTED_READ_KIND_FORBIDDEN", message: "protected_read is valid only on read and aggregate_read capabilities." });
529
+ }
530
+ if (protectedRead.version !== "1")
531
+ errors.push({ path: `${path}.protected_read.version`, code: "INVALID_PROTECTED_READ_VERSION", message: "protected_read.version must be 1." });
532
+ if (protectedRead.mode !== "rows" && protectedRead.mode !== "aggregate")
533
+ errors.push({ path: `${path}.protected_read.mode`, code: "INVALID_PROTECTED_READ_MODE", message: "protected_read.mode must be rows or aggregate." });
534
+ if (protectedRead.mode === "rows" && capability.kind !== "read")
535
+ errors.push({ path: `${path}.kind`, code: "PROTECTED_READ_KIND_MISMATCH", message: "protected rows require capability kind read." });
536
+ if (protectedRead.mode === "aggregate" && capability.kind !== "aggregate_read")
537
+ errors.push({ path: `${path}.kind`, code: "PROTECTED_READ_KIND_MISMATCH", message: "protected aggregates require capability kind aggregate_read." });
538
+ for (const key of ["boundary_digest", "generation_lock_fingerprint"]) {
539
+ if (!isSha256Digest(protectedRead[key]))
540
+ errors.push({ path: `${path}.protected_read.${key}`, code: "INVALID_PROTECTED_READ_DIGEST", message: `${key} must be a canonical sha256 digest.` });
541
+ }
542
+ const args = isRecord(capability.args) ? capability.args : {};
543
+ const referencedArgs = /* @__PURE__ */ new Set();
544
+ const keptOut = new Set(Array.isArray(capability.kept_out_fields) ? capability.kept_out_fields.filter((field) => typeof field === "string") : []);
545
+ const subject = isRecord(capability.subject) ? capability.subject : {};
546
+ const trustedScopeFields = new Set([subject.tenant_key, subject.principal_scope_key].filter((field) => isSafeIdentifier(field)));
547
+ const relationshipName = validateProtectedRelationship(protectedRead.relationship, keptOut, trustedScopeFields, `${path}.protected_read.relationship`, errors);
548
+ if (!isRecord(capability.evidence) || capability.evidence.required !== true || capability.evidence.query_audit !== true) {
549
+ errors.push({
550
+ path: `${path}.evidence`,
551
+ code: "PROTECTED_READ_EVIDENCE_REQUIRED",
552
+ message: "protected reads require evidence.required=true and query_audit=true."
553
+ });
554
+ }
555
+ if (protectedRead.predicates !== void 0) {
556
+ if (!Array.isArray(protectedRead.predicates) || protectedRead.predicates.length > 8) {
557
+ errors.push({ path: `${path}.protected_read.predicates`, code: "INVALID_PROTECTED_PREDICATES", message: "protected_read.predicates must contain at most 8 reviewed predicates." });
558
+ } else {
559
+ protectedRead.predicates.forEach((predicate, index) => {
560
+ const predicatePath = `${path}.protected_read.predicates[${index}]`;
561
+ if (!isRecord(predicate)) {
562
+ errors.push({ path: predicatePath, code: "PROTECTED_PREDICATE_NOT_OBJECT", message: "protected predicate must be an object." });
563
+ return;
564
+ }
565
+ checkUnknownKeys(predicate, PROTECTED_PREDICATE_KEYS, predicatePath, errors);
566
+ validateProtectedFieldReference(predicate.field, predicate.relationship, relationshipName, keptOut, trustedScopeFields, predicatePath, errors);
567
+ if (!["eq", "neq", "lt", "lte", "gt", "gte", "in"].includes(String(predicate.operator))) {
568
+ errors.push({ path: `${predicatePath}.operator`, code: "INVALID_PROTECTED_PREDICATE_OPERATOR", message: "protected predicate operator must be eq, neq, lt, lte, gt, gte, or in." });
569
+ }
570
+ if (predicate.operator === "in") {
571
+ if (predicate.value !== void 0)
572
+ errors.push({ path: `${predicatePath}.value`, code: "PROTECTED_IN_VALUE_FORBIDDEN", message: "in predicates use a fixed values list, not value." });
573
+ if (!Array.isArray(predicate.values) || predicate.values.length < 1 || predicate.values.length > 20 || predicate.values.some((value) => !isJsonScalar(value))) {
574
+ errors.push({ path: `${predicatePath}.values`, code: "INVALID_PROTECTED_IN_VALUES", message: "in predicates require 1 through 20 fixed scalar values." });
575
+ }
576
+ } else {
577
+ if (predicate.values !== void 0)
578
+ errors.push({ path: `${predicatePath}.values`, code: "PROTECTED_VALUES_IN_ONLY", message: "values is valid only for an in predicate." });
579
+ validateProtectedValue(predicate.value, args, referencedArgs, `${predicatePath}.value`, errors);
580
+ }
581
+ });
582
+ }
583
+ }
584
+ if (protectedRead.row_order_by !== void 0) {
585
+ if (!Array.isArray(protectedRead.row_order_by) || protectedRead.row_order_by.length < 1 || protectedRead.row_order_by.length > 3) {
586
+ errors.push({ path: `${path}.protected_read.row_order_by`, code: "INVALID_PROTECTED_ROW_ORDER", message: "row_order_by must contain 1 through 3 fixed sort fields." });
587
+ } else {
588
+ const visible = new Set(Array.isArray(capability.visible_fields) ? capability.visible_fields.filter((field) => typeof field === "string") : []);
589
+ protectedRead.row_order_by.forEach((order, index) => {
590
+ const orderPath = `${path}.protected_read.row_order_by[${index}]`;
591
+ if (!isRecord(order)) {
592
+ errors.push({ path: orderPath, code: "PROTECTED_ROW_ORDER_NOT_OBJECT", message: "row order must be an object." });
593
+ return;
594
+ }
595
+ checkUnknownKeys(order, PROTECTED_ROW_ORDER_KEYS, orderPath, errors);
596
+ if (!isSafeIdentifier(order.field) || !visible.has(String(order.field)) || keptOut.has(String(order.field))) {
597
+ errors.push({ path: `${orderPath}.field`, code: "PROTECTED_ROW_ORDER_FIELD_FORBIDDEN", message: "row order field must be a visible, non-kept-out subject field." });
598
+ }
599
+ if (order.direction !== "asc" && order.direction !== "desc")
600
+ errors.push({ path: `${orderPath}.direction`, code: "INVALID_PROTECTED_ORDER_DIRECTION", message: "order direction must be asc or desc." });
601
+ });
602
+ }
603
+ }
604
+ validateProtectedReadLimits(protectedRead.limits, `${path}.protected_read.limits`, errors);
605
+ if (protectedRead.mode === "rows") {
606
+ if (protectedRead.aggregate !== void 0)
607
+ errors.push({ path: `${path}.protected_read.aggregate`, code: "PROTECTED_AGGREGATE_ROWS_FORBIDDEN", message: "protected row reads must not declare aggregate." });
608
+ if (capability.lookup !== void 0)
609
+ errors.push({ path: `${path}.lookup`, code: "PROTECTED_LOOKUP_FORBIDDEN", message: "protected row reads use only their reviewed predicates and must not also declare legacy lookup." });
610
+ if (!Array.isArray(capability.visible_fields) || capability.visible_fields.length === 0)
611
+ errors.push({ path: `${path}.visible_fields`, code: "PROTECTED_ROW_VISIBLE_FIELDS_REQUIRED", message: "protected row reads require one or more visible fields." });
612
+ const maxRows = isRecord(protectedRead.limits) ? protectedRead.limits.max_rows : void 0;
613
+ if (!Number.isSafeInteger(capability.max_rows) || capability.max_rows !== maxRows) {
614
+ errors.push({ path: `${path}.max_rows`, code: "PROTECTED_ROW_LIMIT_MISMATCH", message: "capability.max_rows must exactly match protected_read.limits.max_rows." });
615
+ }
616
+ } else if (protectedRead.mode === "aggregate") {
617
+ if (capability.lookup !== void 0)
618
+ errors.push({ path: `${path}.lookup`, code: "PROTECTED_AGGREGATE_LOOKUP_FORBIDDEN", message: "protected aggregate reads do not use legacy lookup." });
619
+ if (Array.isArray(capability.visible_fields) && capability.visible_fields.length > 0)
620
+ errors.push({ path: `${path}.visible_fields`, code: "PROTECTED_AGGREGATE_VISIBLE_ROWS_FORBIDDEN", message: "protected aggregate reads return no source row fields." });
621
+ if (protectedRead.row_order_by !== void 0)
622
+ errors.push({ path: `${path}.protected_read.row_order_by`, code: "PROTECTED_AGGREGATE_ROW_ORDER_FORBIDDEN", message: "protected aggregates use aggregate.order_by." });
623
+ validateProtectedAggregate(protectedRead.aggregate, {
624
+ args,
625
+ referencedArgs,
626
+ relationshipName,
627
+ keptOut,
628
+ trustedScopeFields,
629
+ maxGroups: isRecord(protectedRead.limits) ? protectedRead.limits.max_groups : void 0,
630
+ path: `${path}.protected_read.aggregate`,
631
+ errors
632
+ });
633
+ }
634
+ for (const [name, arg] of Object.entries(args)) {
635
+ if (isRecord(arg) && arg.type === "object_array") {
636
+ errors.push({ path: `${path}.args.${name}`, code: "PROTECTED_READ_SCALAR_ARGS_ONLY", message: "protected reads accept only bounded scalar arguments." });
637
+ }
638
+ if (!referencedArgs.has(name)) {
639
+ errors.push({ path: `${path}.args.${name}`, code: "PROTECTED_READ_UNUSED_ARG", message: "every protected-read argument must be selected by a human for one reviewed value position." });
640
+ }
641
+ }
642
+ }
643
+ function validateProtectedRelationship(value, keptOut, trustedScopeFields, path, errors) {
644
+ if (value === void 0)
645
+ return void 0;
646
+ if (!isRecord(value)) {
647
+ errors.push({ path, code: "PROTECTED_RELATIONSHIP_NOT_OBJECT", message: "protected relationship must be an object." });
648
+ return void 0;
649
+ }
650
+ checkUnknownKeys(value, PROTECTED_RELATIONSHIP_KEYS, path, errors);
651
+ for (const key of ["name", "schema", "table", "primary_key", "tenant_key", "local_key", "target_key"]) {
652
+ if (!isSafeIdentifier(value[key]))
653
+ errors.push({ path: `${path}.${key}`, code: "INVALID_PROTECTED_RELATIONSHIP_IDENTIFIER", message: `${key} must be a fixed safe identifier.` });
654
+ }
655
+ if (value.principal_scope_key !== void 0 && !isSafeIdentifier(value.principal_scope_key))
656
+ errors.push({ path: `${path}.principal_scope_key`, code: "INVALID_PROTECTED_RELATIONSHIP_IDENTIFIER", message: "principal_scope_key must be a fixed safe identifier." });
657
+ if (value.cardinality !== "many_to_one" || value.max_fan_out !== 1) {
658
+ errors.push({ path, code: "PROTECTED_RELATIONSHIP_CARDINALITY_FORBIDDEN", message: "the protected-read release permits only an explicitly reviewed many-to-one relationship with max_fan_out 1." });
659
+ }
660
+ if (isSafeIdentifier(value.local_key) && (keptOut.has(value.local_key) || trustedScopeFields.has(value.local_key))) {
661
+ errors.push({
662
+ path: `${path}.local_key`,
663
+ code: "PROTECTED_RELATIONSHIP_LOCAL_KEY_FORBIDDEN",
664
+ message: "the reviewed relationship cannot join through a kept-out or trusted-scope subject field."
665
+ });
666
+ }
667
+ return isSafeIdentifier(value.name) ? value.name : void 0;
668
+ }
669
+ function validateProtectedAggregate(value, input) {
670
+ const { path, errors } = input;
671
+ if (!isRecord(value)) {
672
+ errors.push({ path, code: "PROTECTED_AGGREGATE_REQUIRED", message: "protected aggregate mode requires a frozen aggregate definition." });
673
+ return;
674
+ }
675
+ checkUnknownKeys(value, PROTECTED_AGGREGATE_KEYS, path, errors);
676
+ if (value.counted_entity !== "subject")
677
+ errors.push({ path: `${path}.counted_entity`, code: "INVALID_PROTECTED_COUNTED_ENTITY", message: "the initial protected aggregate release counts the scoped subject entity." });
678
+ const measureNames = /* @__PURE__ */ new Set();
679
+ if (!Array.isArray(value.measures) || value.measures.length < 1 || value.measures.length > 4) {
680
+ errors.push({ path: `${path}.measures`, code: "INVALID_PROTECTED_MEASURES", message: "protected aggregate requires 1 through 4 reviewed measures." });
681
+ } else {
682
+ value.measures.forEach((measure, index) => {
683
+ const measurePath = `${path}.measures[${index}]`;
684
+ if (!isRecord(measure)) {
685
+ errors.push({ path: measurePath, code: "PROTECTED_MEASURE_NOT_OBJECT", message: "protected measure must be an object." });
686
+ return;
687
+ }
688
+ checkUnknownKeys(measure, PROTECTED_MEASURE_KEYS, measurePath, errors);
689
+ validateUniqueIdentifier(measure.name, measureNames, `${measurePath}.name`, "DUPLICATE_PROTECTED_MEASURE_NAME", errors);
690
+ if (!["count", "count_distinct", "sum", "avg"].includes(String(measure.function)))
691
+ errors.push({ path: `${measurePath}.function`, code: "INVALID_PROTECTED_MEASURE_FUNCTION", message: "measure function must be count, count_distinct, sum, or avg." });
692
+ validateProtectedRelationshipReference(measure.relationship, input.relationshipName, `${measurePath}.relationship`, errors);
693
+ if (measure.function === "count") {
694
+ if (measure.field !== void 0)
695
+ errors.push({ path: `${measurePath}.field`, code: "PROTECTED_COUNT_FIELD_FORBIDDEN", message: "count measures count scoped subject rows and must not declare a field." });
696
+ if (measure.relationship !== void 0)
697
+ errors.push({ path: `${measurePath}.relationship`, code: "PROTECTED_COUNT_RELATIONSHIP_FORBIDDEN", message: "count measures count the scoped subject entity, not a joined relation." });
698
+ } else {
699
+ validateProtectedFieldReference(measure.field, measure.relationship, input.relationshipName, input.keptOut, input.trustedScopeFields, measurePath, errors);
700
+ }
701
+ });
702
+ }
703
+ const dimensionNames = /* @__PURE__ */ new Set();
704
+ if (value.dimensions !== void 0) {
705
+ if (!Array.isArray(value.dimensions) || value.dimensions.length > 3) {
706
+ errors.push({ path: `${path}.dimensions`, code: "INVALID_PROTECTED_DIMENSIONS", message: "protected aggregate permits at most 3 reviewed dimensions." });
707
+ } else {
708
+ value.dimensions.forEach((dimension, index) => {
709
+ const dimensionPath = `${path}.dimensions[${index}]`;
710
+ if (!isRecord(dimension)) {
711
+ errors.push({ path: dimensionPath, code: "PROTECTED_DIMENSION_NOT_OBJECT", message: "protected dimension must be an object." });
712
+ return;
713
+ }
714
+ checkUnknownKeys(dimension, PROTECTED_DIMENSION_KEYS, dimensionPath, errors);
715
+ validateUniqueIdentifier(dimension.name, dimensionNames, `${dimensionPath}.name`, "DUPLICATE_PROTECTED_DIMENSION_NAME", errors);
716
+ validateProtectedFieldReference(dimension.field, dimension.relationship, input.relationshipName, input.keptOut, input.trustedScopeFields, dimensionPath, errors);
717
+ });
718
+ }
719
+ }
720
+ if (value.time_bucket !== void 0) {
721
+ const bucketPath = `${path}.time_bucket`;
722
+ if (!isRecord(value.time_bucket)) {
723
+ errors.push({ path: bucketPath, code: "PROTECTED_TIME_BUCKET_NOT_OBJECT", message: "time_bucket must be an object." });
724
+ } else {
725
+ checkUnknownKeys(value.time_bucket, PROTECTED_TIME_BUCKET_KEYS, bucketPath, errors);
726
+ if (!isSafeIdentifier(value.time_bucket.name))
727
+ errors.push({ path: `${bucketPath}.name`, code: "INVALID_PROTECTED_TIME_BUCKET_NAME", message: "time bucket name must be a safe identifier." });
728
+ if (value.time_bucket.bucket !== "day" && value.time_bucket.bucket !== "week" && value.time_bucket.bucket !== "month")
729
+ errors.push({ path: `${bucketPath}.bucket`, code: "INVALID_PROTECTED_TIME_BUCKET", message: "time bucket must be day, week, or month." });
730
+ validateProtectedFieldReference(value.time_bucket.field, value.time_bucket.relationship, input.relationshipName, input.keptOut, input.trustedScopeFields, bucketPath, errors);
731
+ }
732
+ }
733
+ if (value.comparison !== void 0) {
734
+ const comparisonPath = `${path}.comparison`;
735
+ if (!isRecord(value.comparison)) {
736
+ errors.push({ path: comparisonPath, code: "PROTECTED_COMPARISON_NOT_OBJECT", message: "comparison must be an object." });
737
+ } else {
738
+ checkUnknownKeys(value.comparison, PROTECTED_COMPARISON_KEYS, comparisonPath, errors);
739
+ validateProtectedFieldReference(value.comparison.field, value.comparison.relationship, input.relationshipName, input.keptOut, input.trustedScopeFields, comparisonPath, errors);
740
+ if (!Array.isArray(value.comparison.ranges) || value.comparison.ranges.length < 1 || value.comparison.ranges.length > 2) {
741
+ errors.push({ path: `${comparisonPath}.ranges`, code: "INVALID_PROTECTED_COMPARISON_RANGES", message: "comparison requires one or two bounded time ranges." });
742
+ } else {
743
+ value.comparison.ranges.forEach((range, index) => {
744
+ const rangePath = `${comparisonPath}.ranges[${index}]`;
745
+ if (!isRecord(range)) {
746
+ errors.push({ path: rangePath, code: "PROTECTED_COMPARISON_RANGE_NOT_OBJECT", message: "comparison range must be an object." });
747
+ return;
748
+ }
749
+ checkUnknownKeys(range, PROTECTED_RANGE_KEYS, rangePath, errors);
750
+ validateProtectedValue(range.start, input.args, input.referencedArgs, `${rangePath}.start`, errors);
751
+ validateProtectedValue(range.end, input.args, input.referencedArgs, `${rangePath}.end`, errors);
752
+ });
753
+ }
754
+ }
755
+ }
756
+ if (value.order_by !== void 0) {
757
+ const orderPath = `${path}.order_by`;
758
+ if (!isRecord(value.order_by)) {
759
+ errors.push({ path: orderPath, code: "PROTECTED_AGGREGATE_ORDER_NOT_OBJECT", message: "aggregate order_by must be an object." });
760
+ } else {
761
+ checkUnknownKeys(value.order_by, PROTECTED_AGGREGATE_ORDER_KEYS, orderPath, errors);
762
+ if (value.order_by.direction !== "asc" && value.order_by.direction !== "desc")
763
+ errors.push({ path: `${orderPath}.direction`, code: "INVALID_PROTECTED_ORDER_DIRECTION", message: "order direction must be asc or desc." });
764
+ if (value.order_by.kind === "measure") {
765
+ if (!isSafeIdentifier(value.order_by.measure) || !measureNames.has(String(value.order_by.measure)))
766
+ errors.push({ path: `${orderPath}.measure`, code: "UNKNOWN_PROTECTED_ORDER_MEASURE", message: "measure ordering must reference a reviewed measure name." });
767
+ } else if (value.order_by.kind === "time_bucket") {
768
+ if (value.order_by.measure !== void 0)
769
+ errors.push({ path: `${orderPath}.measure`, code: "PROTECTED_TIME_ORDER_MEASURE_FORBIDDEN", message: "time-bucket ordering must not declare a measure." });
770
+ if (!isRecord(value.time_bucket))
771
+ errors.push({ path: orderPath, code: "PROTECTED_TIME_ORDER_REQUIRES_BUCKET", message: "time-bucket ordering requires a reviewed time bucket." });
772
+ } else {
773
+ errors.push({ path: `${orderPath}.kind`, code: "INVALID_PROTECTED_AGGREGATE_ORDER", message: "aggregate order kind must be measure or time_bucket." });
774
+ }
775
+ }
776
+ }
777
+ if (!Number.isSafeInteger(value.top_n) || Number(value.top_n) < 1 || Number(value.top_n) > 100 || Number.isSafeInteger(input.maxGroups) && Number(value.top_n) > Number(input.maxGroups)) {
778
+ errors.push({ path: `${path}.top_n`, code: "INVALID_PROTECTED_TOP_N", message: "top_n must be positive, at most 100, and no greater than limits.max_groups." });
779
+ }
780
+ if (!Number.isSafeInteger(value.minimum_group_size) || Number(value.minimum_group_size) < 2 || Number(value.minimum_group_size) > 1e6) {
781
+ errors.push({ path: `${path}.minimum_group_size`, code: "INVALID_PROTECTED_MINIMUM_GROUP_SIZE", message: "minimum_group_size must be from 2 through 1000000." });
782
+ }
783
+ }
784
+ function validateProtectedReadLimits(value, path, errors) {
785
+ if (!isRecord(value)) {
786
+ errors.push({ path, code: "PROTECTED_READ_LIMITS_REQUIRED", message: "protected_read requires immutable execution, response, extraction, and differencing limits." });
787
+ return;
788
+ }
789
+ checkUnknownKeys(value, PROTECTED_LIMIT_KEYS, path, errors);
790
+ const ceilings = {
791
+ max_rows: 100,
792
+ max_groups: 100,
793
+ max_response_cells: 1e4,
794
+ max_response_bytes: 1048576,
795
+ statement_timeout_ms: 3e4,
796
+ max_queries_per_session: 1e3,
797
+ max_extracted_cells_per_session: 1e5,
798
+ max_differencing_queries: 100,
799
+ rate_limit_per_minute: 120
800
+ };
801
+ for (const [key, maximum] of Object.entries(ceilings)) {
802
+ if (!Number.isSafeInteger(value[key]) || Number(value[key]) < 1 || Number(value[key]) > maximum) {
803
+ errors.push({ path: `${path}.${key}`, code: "INVALID_PROTECTED_READ_LIMIT", message: `${key} must be a positive integer no greater than ${maximum}.` });
804
+ }
805
+ }
806
+ }
807
+ function validateProtectedValue(value, args, referencedArgs, path, errors) {
808
+ if (!isRecord(value)) {
809
+ errors.push({ path, code: "PROTECTED_VALUE_REQUIRED", message: "protected value must be exactly one fixed literal or one reviewed argument reference." });
810
+ return;
811
+ }
812
+ checkUnknownKeys(value, PROTECTED_VALUE_KEYS, path, errors);
813
+ const hasFixed = Object.prototype.hasOwnProperty.call(value, "fixed");
814
+ const hasArg = Object.prototype.hasOwnProperty.call(value, "from_arg");
815
+ if (hasFixed === hasArg) {
816
+ errors.push({ path, code: "PROTECTED_VALUE_EXACTLY_ONE_SOURCE", message: "protected value must declare exactly one of fixed or from_arg." });
817
+ return;
818
+ }
819
+ if (hasFixed && !isJsonScalar(value.fixed))
820
+ errors.push({ path: `${path}.fixed`, code: "INVALID_PROTECTED_FIXED_VALUE", message: "fixed must be a JSON scalar." });
821
+ if (hasArg) {
822
+ const argument = isSafeIdentifier(value.from_arg) ? args[value.from_arg] : void 0;
823
+ if (!isSafeIdentifier(value.from_arg) || !isRecord(argument) || argument.type === "object_array") {
824
+ errors.push({ path: `${path}.from_arg`, code: "UNKNOWN_PROTECTED_VALUE_ARG", message: "from_arg must reference a declared scalar capability argument." });
825
+ } else {
826
+ referencedArgs.add(value.from_arg);
827
+ }
828
+ }
829
+ }
830
+ function validateProtectedFieldReference(field, relationship, relationshipName, keptOut, trustedScopeFields, path, errors) {
831
+ if (!isSafeIdentifier(field)) {
832
+ errors.push({ path: `${path}.field`, code: "INVALID_PROTECTED_FIELD", message: "protected field must be a fixed safe identifier." });
833
+ } else if (relationship === void 0 && (keptOut.has(field) || trustedScopeFields.has(field))) {
834
+ errors.push({ path: `${path}.field`, code: "PROTECTED_FIELD_FORBIDDEN", message: "kept-out and trusted-scope fields cannot be selected, filtered, grouped, sorted, joined, aggregated, or counted distinctly." });
835
+ }
836
+ validateProtectedRelationshipReference(relationship, relationshipName, `${path}.relationship`, errors);
837
+ }
838
+ function validateProtectedRelationshipReference(value, relationshipName, path, errors) {
839
+ if (value === void 0)
840
+ return;
841
+ if (!isSafeIdentifier(value) || value !== relationshipName)
842
+ errors.push({ path, code: "UNKNOWN_PROTECTED_RELATIONSHIP", message: "relationship must reference the capability's one reviewed many-to-one relationship." });
843
+ }
844
+ function validateUniqueIdentifier(value, seen, path, code, errors) {
845
+ if (!isSafeIdentifier(value)) {
846
+ errors.push({ path, code: "INVALID_PROTECTED_ALIAS", message: "reviewed aliases must be safe identifiers." });
847
+ return;
848
+ }
849
+ if (seen.has(value))
850
+ errors.push({ path, code, message: `Duplicate reviewed alias: ${value}.` });
851
+ seen.add(value);
852
+ }
460
853
  function validateAggregateRead(capability, path, errors) {
461
854
  const aggregate = capability.aggregate;
462
855
  if (!isRecord(aggregate)) {
@@ -1242,6 +1635,9 @@ function isQualifiedName(value) {
1242
1635
  function isQualifiedOrSafeName(value) {
1243
1636
  return isSafeIdentifier(value) || isQualifiedName(value);
1244
1637
  }
1638
+ function isSha256Digest(value) {
1639
+ return typeof value === "string" && /^sha256:[a-f0-9]{64}$/.test(value);
1640
+ }
1245
1641
  function isPositiveInteger(value) {
1246
1642
  return Number.isInteger(value) && Number(value) > 0;
1247
1643
  }
@@ -1252,7 +1648,7 @@ function isJsonScalar(value) {
1252
1648
  return value === null || typeof value === "string" || typeof value === "boolean" || isFiniteNumber(value);
1253
1649
  }
1254
1650
 
1255
- // node_modules/.pnpm/@synapsor+spec@1.4.2/node_modules/@synapsor/spec/dist/normalize.js
1651
+ // packages/spec/dist/normalize.js
1256
1652
  function normalizeContract(input) {
1257
1653
  assertValidContract(input);
1258
1654
  return sortJson(input);
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAYA,OAAO,EAAoX,KAAK,WAAW,EAAyJ,MAAM,6BAA6B,CAAC;AAIxkB,OAAO,EAsBL,KAAK,qBAAqB,EAK3B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAmI,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAqG,KAAK,YAAY,EAAwB,MAAM,2BAA2B,CAAC;AAEnY,OAAO,EAQL,KAAK,gBAAgB,EAEtB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAaL,KAAK,yBAAyB,EAG/B,MAAM,8BAA8B,CAAC;AAuWtC,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAqE1D;AAwID,KAAK,SAAS,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAE9E,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CACvC,GACL,OAAO,CAAC,MAAM,CAAC,CA+YjB;AA+tJD,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAc/H;AAojBD,wBAAsB,6BAA6B,CACjD,GAAG,EAAE,YAAY,EACjB,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC,OAAO,CAAC,IAAI,CAAC,CA4Gf;AAugDD,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,yBAAyB,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,CAKxH;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,qBAAqB,EAC7B,WAAW,EAAE,yBAAyB,EACtC,OAAO,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,EAC1C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,kBAAkB,GAAG,kBAAkB,GAAG,kBAAkB,CAgH9D"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAYA,OAAO,EAA2a,KAAK,WAAW,EAAyJ,MAAM,6BAA6B,CAAC;AAI/nB,OAAO,EAsBL,KAAK,qBAAqB,EAK3B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAmI,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAqG,KAAK,YAAY,EAAwB,MAAM,2BAA2B,CAAC;AAEnY,OAAO,EAQL,KAAK,gBAAgB,EAEtB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAaL,KAAK,yBAAyB,EAG/B,MAAM,8BAA8B,CAAC;AAgXtC,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAsE1D;AAwID,KAAK,SAAS,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAE9E,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CACvC,GACL,OAAO,CAAC,MAAM,CAAC,CA+YjB;AA4vJD,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAc/H;AAojBD,wBAAsB,6BAA6B,CACjD,GAAG,EAAE,YAAY,EACjB,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC,OAAO,CAAC,IAAI,CAAC,CA4Gf;AA6sDD,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,yBAAyB,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,CAKxH;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,qBAAqB,EAC7B,WAAW,EAAE,yBAAyB,EACtC,OAAO,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,EAC1C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,kBAAkB,GAAG,kBAAkB,GAAG,kBAAkB,CAgH9D"}
@@ -10,6 +10,8 @@ export type LocalUiOptions = {
10
10
  csrfToken?: string;
11
11
  allowRemoteBind?: boolean;
12
12
  tour?: boolean;
13
+ boundaryRoot?: string;
14
+ projectRoot?: string;
13
15
  storeAccess?: LocalUiStoreAccess;
14
16
  safeActionPreview?: SafeActionPreview;
15
17
  };
@@ -1 +1 @@
1
- {"version":3,"file":"local-ui.d.ts","sourceRoot":"","sources":["../src/local-ui.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;AAKjG,OAAO,EAAE,aAAa,EAAgD,MAAM,iCAAiC,CAAC;AAW9G,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE1C,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;CAClB,KAAK,OAAO,CAAC;IACZ,YAAY,EAAE,UAAU,MAAM,EAAE,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,uBAAuB,EAAE,OAAO,CAAC;CAClC,CAAC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,EACjC,IAAI,EAAE,MAAM,GAAG,OAAO,EACtB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,CAAC,KAClC,OAAO,CAAC,CAAC,CAAC,CAAC;AAEhB,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CAAC;AAEF,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAkD7F"}
1
+ {"version":3,"file":"local-ui.d.ts","sourceRoot":"","sources":["../src/local-ui.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;AAKjG,OAAO,EAAE,aAAa,EAAgD,MAAM,iCAAiC,CAAC;AA0B9G,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE1C,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;CAClB,KAAK,OAAO,CAAC;IACZ,YAAY,EAAE,UAAU,MAAM,EAAE,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,uBAAuB,EAAE,OAAO,CAAC;CAClC,CAAC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,EACjC,IAAI,EAAE,MAAM,GAAG,OAAO,EACtB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,CAAC,KAClC,OAAO,CAAC,CAAC,CAAC,CAAC;AAEhB,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CAAC;AAEF,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAmD7F"}