@zuplo/cli 7.3.2 → 7.4.1

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 (32) hide show
  1. package/dist/cli.js +2 -0
  2. package/dist/cli.js.map +1 -1
  3. package/dist/cmds/lint.d.ts +9 -0
  4. package/dist/cmds/lint.d.ts.map +1 -0
  5. package/dist/cmds/lint.js +67 -0
  6. package/dist/cmds/lint.js.map +1 -0
  7. package/dist/lint/handler.d.ts +10 -0
  8. package/dist/lint/handler.d.ts.map +1 -0
  9. package/dist/lint/handler.js +60 -0
  10. package/dist/lint/handler.js.map +1 -0
  11. package/dist/lint/resolve-binary.d.ts +20 -0
  12. package/dist/lint/resolve-binary.d.ts.map +1 -0
  13. package/dist/lint/resolve-binary.js +71 -0
  14. package/dist/lint/resolve-binary.js.map +1 -0
  15. package/dist/lint/resolve-binary.test.d.ts +2 -0
  16. package/dist/lint/resolve-binary.test.d.ts.map +1 -0
  17. package/dist/lint/resolve-binary.test.js +155 -0
  18. package/dist/lint/resolve-binary.test.js.map +1 -0
  19. package/dist/tsconfig.tsbuildinfo +1 -1
  20. package/node_modules/@zuplo/core/package.json +1 -1
  21. package/node_modules/@zuplo/graphql/package.json +1 -1
  22. package/node_modules/@zuplo/openapi-tools/package.json +1 -1
  23. package/node_modules/@zuplo/otel/package.json +1 -1
  24. package/node_modules/@zuplo/runtime/out/esm/{chunk-YOMMW6SX.js → chunk-JKIKT5LB.js} +116 -116
  25. package/node_modules/@zuplo/runtime/out/esm/chunk-JKIKT5LB.js.map +1 -0
  26. package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
  27. package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +1 -1
  28. package/node_modules/@zuplo/runtime/out/types/index.d.ts +47 -65
  29. package/node_modules/@zuplo/runtime/package.json +1 -1
  30. package/package.json +13 -6
  31. package/node_modules/@zuplo/runtime/out/esm/chunk-YOMMW6SX.js.map +0 -1
  32. /package/node_modules/@zuplo/runtime/out/esm/{chunk-YOMMW6SX.js.LEGAL.txt → chunk-JKIKT5LB.js.LEGAL.txt} +0 -0
@@ -345,8 +345,9 @@ export declare interface AIGatewayConfigurationLoaderV2InboundPolicyOptions {
345
345
  * identifiers, API keys and other credentials) using the in-gateway DLP
346
346
  * engine, and applies per-rule actions: mask, block, or log. Detection runs
347
347
  * entirely inside the gateway; nothing is sent to a third-party scanning
348
- * service. Streaming responses are scanned as they stream, chunk by chunk
349
- * with a sliding boundary window, rather than being buffered to the end.
348
+ * service. Streaming responses are scanned as they stream by default (chunk
349
+ * by chunk with a sliding boundary window); `streaming.mode: "buffer"`
350
+ * instead collects the whole response and scans it once as one document.
350
351
  *
351
352
  * Options are validated at request time and invalid options fail closed with
352
353
  * a ConfigurationError. Content that cannot be inspected is denied by
@@ -367,13 +368,13 @@ export declare function AIGatewayDlpInboundPolicy(
367
368
  ): Promise<ZuploRequest | Response>;
368
369
 
369
370
  /**
370
- * The options for the Data Loss Prevention (DLP) policy. Scans the content of AI requests and responses — system prompts, messages, and tool-call arguments — for sensitive data such as credit cards, national identifiers, and API keys, applying a per-rule action (mask, block, or log). Detection runs entirely inside the gateway and streaming responses are scanned as they stream.
371
+ * The options for the Data Loss Prevention (DLP) policy. Scans the content of AI requests and responses — system prompts, messages, and tool-call arguments — for sensitive data such as credit cards, national identifiers, and API keys, applying a per-rule action (mask, block, or log). Detection runs entirely inside the gateway; streaming responses are scanned as they stream (or collected and scanned whole with `streaming.mode: "buffer"`).
371
372
  * @public
372
373
  */
373
374
  export declare interface AIGatewayDlpInboundPolicyOptions {
374
375
  rules: DlpRules;
375
376
  /**
376
- * Your own detection rules alongside the built-ins: the same rule object plus a `name`, a regex `pattern`, and optional `context` words.
377
+ * Your own detectors: a `name`, a regex `pattern`, and optional `context` words. A detector does nothing by itself — activate it by name inside `rules.inbound` or `rules.outbound`, exactly like a built-in type, with its own action, detection level, and mask per direction.
377
378
  */
378
379
  customRules?: DlpCustomRule[];
379
380
  /**
@@ -4861,7 +4862,7 @@ declare interface DlpCustomPattern_2 {
4861
4862
 
4862
4863
  declare interface DlpCustomRule {
4863
4864
  /**
4864
- * Identifier reported in findings and block details for this rule.
4865
+ * The detector's name — the key you use to activate it inside `rules.inbound` or `rules.outbound`, exactly like a built-in type id. Must be distinct and must not reuse a built-in type id or group selector.
4865
4866
  */
4866
4867
  name: string;
4867
4868
  /**
@@ -4869,68 +4870,16 @@ declare interface DlpCustomRule {
4869
4870
  */
4870
4871
  pattern: string;
4871
4872
  /**
4872
- * Context words for this rule. With `detection: "corroborated"` the rule only fires when one of these words appears near the match.
4873
+ * Context words for this detector. An activation with `detection: "corroborated"` then only fires when one of these words appears near the match.
4873
4874
  */
4874
4875
  context?: string[];
4875
- /**
4876
- * What happens when this rule matches, in BOTH directions. `mask` replaces the matched text with a placeholder and the conversation continues; `block` rejects the request or terminates the response with an error naming only the rule's name (never the values); `log` records a finding and lets the traffic pass unchanged; `off` disables the rule. A rule states either `action` or the directional pair (`inboundAction`/`outboundAction`), never both.
4877
- */
4878
- action?: "mask" | "block" | "log" | "off";
4879
- /**
4880
- * What happens when this rule matches in what callers send the model. Use with `outboundAction` to give the rule different behavior per direction. Omitting it (or `off`) leaves the inbound direction unscanned for this rule. Cannot be combined with `action`.
4881
- */
4882
- inboundAction?: "mask" | "block" | "log" | "off";
4883
- /**
4884
- * What happens when this rule matches in what the model sends back. Omitting it (or `off`) leaves the outbound direction unscanned for this rule. Cannot be combined with `action`.
4885
- */
4886
- outboundAction?: "mask" | "block" | "log" | "off";
4887
- /**
4888
- * How much evidence a match needs before this rule acts. `corroborated` additionally requires one of the type's context words near the match (types that define no context words behave as `standard`); `standard` uses the catalog as tuned — distinctive shapes act on their own while ambiguous shapes need nearby context; `aggressive` counts every pattern match and is false-positive-prone — pair it with the `log` action for audits. Overrides the policy-level `detection` for this rule.
4889
- */
4890
- detection?: "corroborated" | "standard" | "aggressive";
4891
- /**
4892
- * Replacement text for this rule's masked matches. The `{type}` token inserts the detected type id in UPPER_SNAKE form, so the default turns a matched email into `[CONTACT_EMAIL]` — typed placeholders keep masked conversations legible to the model. Set a literal like `[REDACTED]` to hide the type.
4893
- */
4894
- mask?: string;
4895
- partialMask?: DlpPartialMask;
4896
- }
4897
-
4898
- declare interface DlpPartialMask {
4899
- /**
4900
- * Keep the last N characters of the matched value unmasked and replace the rest with `*`, preserving length (for example `**** **** **** 4242`). Values no longer than N characters are fully masked.
4901
- */
4902
- keepLast: number;
4903
- }
4904
-
4905
- declare interface DlpRule {
4906
- /**
4907
- * What happens when this type is found, in BOTH directions. `mask` replaces the matched text with a placeholder and the conversation continues; `block` rejects the request or terminates the response with an error naming only the detected types (never the values); `log` records a finding and lets the traffic pass unchanged — use it to trial a rule before enforcing it; `off` excludes this type from a group enabled by a broader key. A rule states either `action` or the directional pair (`inboundAction`/`outboundAction`), never both.
4908
- */
4909
- action?: "mask" | "block" | "log" | "off";
4910
- /**
4911
- * What happens when this type is found in what callers send the model (system prompt, message text, and tool-call arguments). Use with `outboundAction` to give one type different behavior per direction — for example mask PII on the way in and block it on the way out. Omitting it (or `off`) leaves the inbound direction unscanned for this type. Cannot be combined with `action`.
4912
- */
4913
- inboundAction?: "mask" | "block" | "log" | "off";
4914
- /**
4915
- * What happens when this type is found in what the model sends back (buffered responses whole, streaming responses as they stream). Omitting it (or `off`) leaves the outbound direction unscanned for this type. Cannot be combined with `action`.
4916
- */
4917
- outboundAction?: "mask" | "block" | "log" | "off";
4918
- /**
4919
- * How much evidence a match needs before this rule acts. `corroborated` additionally requires one of the type's context words near the match (types that define no context words behave as `standard`); `standard` uses the catalog as tuned — distinctive shapes act on their own while ambiguous shapes need nearby context; `aggressive` counts every pattern match and is false-positive-prone — pair it with the `log` action for audits. Overrides the policy-level `detection` for this rule.
4920
- */
4921
- detection?: "corroborated" | "standard" | "aggressive";
4922
- /**
4923
- * Replacement text for this rule's masked matches. The `{type}` token inserts the detected type id in UPPER_SNAKE form, so the default turns a matched email into `[CONTACT_EMAIL]` — typed placeholders keep masked conversations legible to the model. Set a literal like `[REDACTED]` to hide the type.
4924
- */
4925
- mask?: string;
4926
- partialMask?: DlpPartialMask;
4927
4876
  }
4928
4877
 
4929
4878
  /**
4930
- * What to find and what to do about it. Each key is a built-in data type id (like `id-us-ssn`) or a group selector (like `pii` or `secret`, plus any dash-aligned id prefix such as `secret-aws`); each value is a rule object stating either one `action` for both directions or a directional pair (`inboundAction`/`outboundAction`) — for example mask PII inbound and block it outbound. Types you do not mention are not scanned. The most specific key wins — an exact id beats a prefix beats a group — and the winning entry decides everything for its type. When one stretch of text matches multiple rules, the severest action wins (block > mask > log). At least one rule must scan something.
4879
+ * What to find in this direction and what to do about it. Each key is a built-in data type id (like `id-us-ssn`), a group selector (like `pii` or `secret`, plus any dash-aligned id prefix such as `secret-aws`), or one of your custom detectors by name; each value is a rule object whose required `action` says what happens on a match. Types you do not mention are not scanned in this direction. The most specific key wins — an exact id beats a prefix beats a group — and the winning entry decides everything for its type in this direction. When one stretch of text matches multiple rules, the severest action wins (block > mask > log).
4931
4880
  * @public
4932
4881
  */
4933
- declare interface DlpRules {
4882
+ declare interface DlpDirectionRules {
4934
4883
  contact?: DlpRule;
4935
4884
  finance?: DlpRule;
4936
4885
  "finance-us"?: DlpRule;
@@ -5014,23 +4963,56 @@ declare interface DlpRules {
5014
4963
  "secret-terraform"?: DlpRule;
5015
4964
  "secret-twilio"?: DlpRule;
5016
4965
  "secret-zuplo"?: DlpRule;
4966
+ [k: string]: unknown;
4967
+ }
4968
+
4969
+ declare interface DlpPartialMask {
4970
+ /**
4971
+ * Keep the last N characters of the matched value unmasked and replace the rest with `*`, preserving length (for example `**** **** **** 4242`). Values no longer than N characters are fully masked.
4972
+ */
4973
+ keepLast: number;
4974
+ }
4975
+
4976
+ declare interface DlpRule {
4977
+ /**
4978
+ * What happens when this rule matches in this direction. `mask` replaces the matched text with a placeholder and the conversation continues; `block` rejects the request or terminates the response with an error naming only the detected types (never the values); `log` records a finding and lets the traffic pass unchanged — use it to trial a rule before enforcing it; `off` excludes this type from a group enabled by a broader key in the same section.
4979
+ */
4980
+ action: "mask" | "block" | "log" | "off";
4981
+ /**
4982
+ * How much evidence a match needs before this rule acts. `corroborated` additionally requires one of the type's context words near the match (types that define no context words behave as `standard`); `standard` uses the catalog as tuned — distinctive shapes act on their own while ambiguous shapes need nearby context; `aggressive` counts every pattern match and is false-positive-prone — pair it with the `log` action for audits. Overrides the policy-level `detection` for this rule.
4983
+ */
4984
+ detection?: "corroborated" | "standard" | "aggressive";
4985
+ /**
4986
+ * Replacement text for this rule's masked matches. The `{type}` token inserts the detected type id in UPPER_SNAKE form, so the default turns a matched email into `[CONTACT_EMAIL]` — typed placeholders keep masked conversations legible to the model. Set a literal like `[REDACTED]` to hide the type.
4987
+ */
4988
+ mask?: string;
4989
+ partialMask?: DlpPartialMask;
4990
+ }
4991
+
4992
+ /**
4993
+ * The scan configuration, split by direction: `inbound` covers what callers send the model (system prompt, message text, and tool-call arguments); `outbound` covers what the model sends back (buffered responses whole, streaming responses as they stream). Each direction you include is scanned; each you omit is left untouched — there is no "both" shorthand and no mirroring, so wanting the same behavior on both sides means stating it in both sections. At least one section must enable at least one rule.
4994
+ * @public
4995
+ */
4996
+ declare interface DlpRules {
4997
+ inbound?: DlpDirectionRules;
4998
+ outbound?: DlpDirectionRules;
5017
4999
  }
5018
5000
 
5019
5001
  /**
5020
- * Tuning for streaming (SSE) response scanning. Each chunk is held until the boundary scan that includes its successor passes, then released so values split across chunks are always fully maskable, at the cost of one chunk of latency.
5002
+ * How streaming (SSE) responses are inspected. `stream` (the default) scans deltas as they flow, holding each chunk until the boundary scan that includes its successor passes — values split across chunks stay maskable at the cost of one chunk of latency. `buffer` collects the entire response and scans it once as one document — exact detection for values of any length, and a blocked response is a clean 400 because nothing has been delivered yet — at the cost of the client waiting for the full generation. `off` passes streaming responses through unscanned.
5021
5003
  * @public
5022
5004
  */
5023
5005
  declare interface DlpStreamingSettings {
5024
5006
  /**
5025
- * Scan streaming responses. When false, streaming responses pass through unscanned even when rules cover the outbound direction.
5007
+ * `stream` scans deltas in flight with the windowed scanner. `buffer` holds the entire response and scans it once, exactly like a non-streaming response: values of any length are caught (no carry window) and a block is a native 400 error instead of a mid-stream termination, but the client receives nothing until the model finishes. `off` skips scanning of streaming responses entirely, even when rules cover the outbound direction.
5026
5008
  */
5027
- enabled?: boolean;
5009
+ mode?: "stream" | "buffer" | "off";
5028
5010
  /**
5029
- * Scan across chunk boundaries using a carried tail of already-scanned text. When false, each chunk is scanned alone and released immediately — lower cost, but values split across two chunks are missed.
5011
+ * Scan across chunk boundaries using a carried tail of already-scanned text. When false, each chunk is scanned alone and released immediately — lower cost, but values split across two chunks are missed. Applies to `stream` mode only.
5030
5012
  */
5031
5013
  boundaryScan?: boolean;
5032
5014
  /**
5033
- * How many trailing characters are carried from one chunk into the next boundary scan. Bounds memory and re-scan cost; must be larger than the longest value you need to catch.
5015
+ * How many trailing characters are carried from one chunk into the next boundary scan. Bounds memory and re-scan cost; must be larger than the longest value you need to catch. Applies to `stream` mode only — `buffer` mode always scans the complete text.
5034
5016
  */
5035
5017
  maxCarryChars?: number;
5036
5018
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zuplo/runtime",
3
3
  "type": "module",
4
- "version": "7.3.2",
4
+ "version": "7.4.1",
5
5
  "repository": "https://github.com/zuplo/zuplo",
6
6
  "author": "Zuplo, Inc.",
7
7
  "exports": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zuplo/cli",
3
- "version": "7.3.2",
3
+ "version": "7.4.1",
4
4
  "repository": "https://github.com/zuplo/zuplo",
5
5
  "author": "Zuplo, Inc.",
6
6
  "type": "module",
@@ -28,10 +28,10 @@
28
28
  "@opentelemetry/api": "1.9.0",
29
29
  "@opentelemetry/api-logs": "0.220.0",
30
30
  "@swc/core": "1.10.18",
31
- "@zuplo/core": "7.3.2",
31
+ "@zuplo/core": "7.4.1",
32
32
  "@zuplo/editor": "1.0.31094607111",
33
- "@zuplo/openapi-tools": "7.3.2",
34
- "@zuplo/runtime": "7.3.2",
33
+ "@zuplo/openapi-tools": "7.4.1",
34
+ "@zuplo/runtime": "7.4.1",
35
35
  "chalk": "5.4.1",
36
36
  "chokidar": "3.5.3",
37
37
  "cookie": "1.0.2",
@@ -62,8 +62,15 @@
62
62
  "workerd": "1.20241230.0",
63
63
  "yargs": "17.7.2",
64
64
  "zod": "4.4.3",
65
- "@zuplo/graphql": "7.3.2",
66
- "@zuplo/otel": "7.3.2"
65
+ "@zuplo/graphql": "7.4.1",
66
+ "@zuplo/otel": "7.4.1"
67
+ },
68
+ "optionalDependencies": {
69
+ "@zuplo/lint-darwin-arm64": "7.4.1",
70
+ "@zuplo/lint-darwin-x64": "7.4.1",
71
+ "@zuplo/lint-linux-x64": "7.4.1",
72
+ "@zuplo/lint-linux-arm64": "7.4.1",
73
+ "@zuplo/lint-win32-x64": "7.4.1"
67
74
  },
68
75
  "bundleDependencies": [
69
76
  "@inquirer/prompts",