@kindgi/cli 0.1.8 → 0.1.9-rc.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 (270) hide show
  1. package/README.md +59 -2
  2. package/dist/api-address.d.ts +104 -12
  3. package/dist/api-address.d.ts.map +1 -1
  4. package/dist/api-address.js +169 -30
  5. package/dist/api-address.js.map +1 -1
  6. package/dist/build/host-install.d.ts.map +1 -1
  7. package/dist/build/host-install.js +5 -2
  8. package/dist/build/host-install.js.map +1 -1
  9. package/dist/cli.js +12 -2
  10. package/dist/cli.js.map +1 -1
  11. package/dist/commands/approvals.d.ts.map +1 -1
  12. package/dist/commands/approvals.js +15 -3
  13. package/dist/commands/approvals.js.map +1 -1
  14. package/dist/commands/auth.d.ts.map +1 -1
  15. package/dist/commands/auth.js +27 -0
  16. package/dist/commands/auth.js.map +1 -1
  17. package/dist/commands/build.d.ts +18 -0
  18. package/dist/commands/build.d.ts.map +1 -1
  19. package/dist/commands/build.js +118 -13
  20. package/dist/commands/build.js.map +1 -1
  21. package/dist/commands/conversations.d.ts.map +1 -1
  22. package/dist/commands/conversations.js +13 -3
  23. package/dist/commands/conversations.js.map +1 -1
  24. package/dist/commands/deploy.d.ts.map +1 -1
  25. package/dist/commands/deploy.js +235 -53
  26. package/dist/commands/deploy.js.map +1 -1
  27. package/dist/commands/deployments.d.ts +3 -0
  28. package/dist/commands/deployments.d.ts.map +1 -0
  29. package/dist/commands/deployments.js +196 -0
  30. package/dist/commands/deployments.js.map +1 -0
  31. package/dist/commands/doctor.d.ts +1 -5
  32. package/dist/commands/doctor.d.ts.map +1 -1
  33. package/dist/commands/doctor.js +42 -22
  34. package/dist/commands/doctor.js.map +1 -1
  35. package/dist/commands/egress.d.ts +9 -0
  36. package/dist/commands/egress.d.ts.map +1 -0
  37. package/dist/commands/egress.js +40 -0
  38. package/dist/commands/egress.js.map +1 -0
  39. package/dist/commands/env-scoped.d.ts +5 -0
  40. package/dist/commands/env-scoped.d.ts.map +1 -1
  41. package/dist/commands/env-scoped.js +64 -19
  42. package/dist/commands/env-scoped.js.map +1 -1
  43. package/dist/commands/env.d.ts.map +1 -1
  44. package/dist/commands/env.js +91 -30
  45. package/dist/commands/env.js.map +1 -1
  46. package/dist/commands/environments.d.ts +6 -0
  47. package/dist/commands/environments.d.ts.map +1 -0
  48. package/dist/commands/environments.js +166 -0
  49. package/dist/commands/environments.js.map +1 -0
  50. package/dist/commands/exports.d.ts.map +1 -1
  51. package/dist/commands/exports.js +118 -3
  52. package/dist/commands/exports.js.map +1 -1
  53. package/dist/commands/feedback.d.ts +1 -2
  54. package/dist/commands/feedback.d.ts.map +1 -1
  55. package/dist/commands/feedback.js +55 -24
  56. package/dist/commands/feedback.js.map +1 -1
  57. package/dist/commands/helpers.d.ts +6 -0
  58. package/dist/commands/helpers.d.ts.map +1 -1
  59. package/dist/commands/helpers.js +8 -0
  60. package/dist/commands/helpers.js.map +1 -1
  61. package/dist/commands/index.d.ts.map +1 -1
  62. package/dist/commands/index.js +12 -0
  63. package/dist/commands/index.js.map +1 -1
  64. package/dist/commands/license.d.ts +3 -0
  65. package/dist/commands/license.d.ts.map +1 -1
  66. package/dist/commands/license.js +1 -1
  67. package/dist/commands/license.js.map +1 -1
  68. package/dist/commands/people.d.ts.map +1 -1
  69. package/dist/commands/people.js +105 -10
  70. package/dist/commands/people.js.map +1 -1
  71. package/dist/commands/projects.d.ts.map +1 -1
  72. package/dist/commands/projects.js +133 -11
  73. package/dist/commands/projects.js.map +1 -1
  74. package/dist/commands/promote.d.ts +38 -0
  75. package/dist/commands/promote.d.ts.map +1 -0
  76. package/dist/commands/promote.js +371 -0
  77. package/dist/commands/promote.js.map +1 -0
  78. package/dist/commands/proposals.d.ts.map +1 -1
  79. package/dist/commands/proposals.js +2 -1
  80. package/dist/commands/proposals.js.map +1 -1
  81. package/dist/commands/providers.d.ts.map +1 -1
  82. package/dist/commands/providers.js +29 -5
  83. package/dist/commands/providers.js.map +1 -1
  84. package/dist/commands/schedules.d.ts.map +1 -1
  85. package/dist/commands/schedules.js +30 -2
  86. package/dist/commands/schedules.js.map +1 -1
  87. package/dist/commands/secrets.d.ts.map +1 -1
  88. package/dist/commands/secrets.js +65 -40
  89. package/dist/commands/secrets.js.map +1 -1
  90. package/dist/commands/sign-in.d.ts +3 -0
  91. package/dist/commands/sign-in.d.ts.map +1 -0
  92. package/dist/commands/sign-in.js +61 -0
  93. package/dist/commands/sign-in.js.map +1 -0
  94. package/dist/commands/sites.d.ts +3 -0
  95. package/dist/commands/sites.d.ts.map +1 -0
  96. package/dist/commands/sites.js +244 -0
  97. package/dist/commands/sites.js.map +1 -0
  98. package/dist/commands/tools.d.ts.map +1 -1
  99. package/dist/commands/tools.js +2 -2
  100. package/dist/commands/tools.js.map +1 -1
  101. package/dist/commands/types.d.ts +11 -0
  102. package/dist/commands/types.d.ts.map +1 -1
  103. package/dist/commands/webhooks.d.ts.map +1 -1
  104. package/dist/commands/webhooks.js +38 -2
  105. package/dist/commands/webhooks.js.map +1 -1
  106. package/dist/config.d.ts +13 -0
  107. package/dist/config.d.ts.map +1 -1
  108. package/dist/config.js +20 -7
  109. package/dist/config.js.map +1 -1
  110. package/dist/context.d.ts +38 -2
  111. package/dist/context.d.ts.map +1 -1
  112. package/dist/context.js +12 -1
  113. package/dist/context.js.map +1 -1
  114. package/dist/deploy/defaults.d.ts.map +1 -1
  115. package/dist/deploy/defaults.js +7 -1
  116. package/dist/deploy/defaults.js.map +1 -1
  117. package/dist/deploy/pack-service-text.d.ts +29 -0
  118. package/dist/deploy/pack-service-text.d.ts.map +1 -0
  119. package/dist/deploy/pack-service-text.js +72 -0
  120. package/dist/deploy/pack-service-text.js.map +1 -0
  121. package/dist/deploy/post.d.ts +17 -4
  122. package/dist/deploy/post.d.ts.map +1 -1
  123. package/dist/deploy/post.js +177 -60
  124. package/dist/deploy/post.js.map +1 -1
  125. package/dist/deploy/promotion-path.d.ts +44 -0
  126. package/dist/deploy/promotion-path.d.ts.map +1 -0
  127. package/dist/deploy/promotion-path.js +86 -0
  128. package/dist/deploy/promotion-path.js.map +1 -0
  129. package/dist/deploy/response.d.ts +3 -0
  130. package/dist/deploy/response.d.ts.map +1 -1
  131. package/dist/deploy/response.js +66 -12
  132. package/dist/deploy/response.js.map +1 -1
  133. package/dist/deploy/runners.d.ts +99 -5
  134. package/dist/deploy/runners.d.ts.map +1 -1
  135. package/dist/dev/java-builder.d.ts.map +1 -1
  136. package/dist/dev/java-builder.js +19 -3
  137. package/dist/dev/java-builder.js.map +1 -1
  138. package/dist/dev/python-builder.d.ts.map +1 -1
  139. package/dist/dev/python-builder.js +18 -3
  140. package/dist/dev/python-builder.js.map +1 -1
  141. package/dist/dev/runtime-container.d.ts +28 -3
  142. package/dist/dev/runtime-container.d.ts.map +1 -1
  143. package/dist/dev/runtime-container.js +103 -36
  144. package/dist/dev/runtime-container.js.map +1 -1
  145. package/dist/dev/runtime-image.d.ts +1 -1
  146. package/dist/dev/runtime-image.d.ts.map +1 -1
  147. package/dist/dev/runtime-image.js +1 -1
  148. package/dist/dev/runtime-image.js.map +1 -1
  149. package/dist/dev/scala-builder.d.ts.map +1 -1
  150. package/dist/dev/scala-builder.js +55 -21
  151. package/dist/dev/scala-builder.js.map +1 -1
  152. package/dist/dev/shared-watch.d.ts +30 -0
  153. package/dist/dev/shared-watch.d.ts.map +1 -1
  154. package/dist/dev/shared-watch.js +46 -1
  155. package/dist/dev/shared-watch.js.map +1 -1
  156. package/dist/env/pack-env-hint.d.ts +52 -0
  157. package/dist/env/pack-env-hint.d.ts.map +1 -0
  158. package/dist/env/pack-env-hint.js +57 -0
  159. package/dist/env/pack-env-hint.js.map +1 -0
  160. package/dist/env/pack-env-plan.d.ts +2 -0
  161. package/dist/env/pack-env-plan.d.ts.map +1 -1
  162. package/dist/env/pack-env-plan.js +2 -1
  163. package/dist/env/pack-env-plan.js.map +1 -1
  164. package/dist/env-projects.d.ts +23 -0
  165. package/dist/env-projects.d.ts.map +1 -0
  166. package/dist/env-projects.js +28 -0
  167. package/dist/env-projects.js.map +1 -0
  168. package/dist/exports/create.d.ts +71 -0
  169. package/dist/exports/create.d.ts.map +1 -0
  170. package/dist/exports/create.js +576 -0
  171. package/dist/exports/create.js.map +1 -0
  172. package/dist/exports/plan.d.ts +69 -0
  173. package/dist/exports/plan.d.ts.map +1 -0
  174. package/dist/exports/plan.js +496 -0
  175. package/dist/exports/plan.js.map +1 -0
  176. package/dist/exports/reader.d.ts +48 -0
  177. package/dist/exports/reader.d.ts.map +1 -0
  178. package/dist/exports/reader.js +181 -0
  179. package/dist/exports/reader.js.map +1 -0
  180. package/dist/feedback/entries.d.ts +53 -0
  181. package/dist/feedback/entries.d.ts.map +1 -0
  182. package/dist/feedback/entries.js +173 -0
  183. package/dist/feedback/entries.js.map +1 -0
  184. package/dist/feedback/intake.d.ts +37 -0
  185. package/dist/feedback/intake.d.ts.map +1 -0
  186. package/dist/feedback/intake.js +101 -0
  187. package/dist/feedback/intake.js.map +1 -0
  188. package/dist/feedback/protocol.d.ts +111 -0
  189. package/dist/feedback/protocol.d.ts.map +1 -0
  190. package/dist/feedback/protocol.js +143 -0
  191. package/dist/feedback/protocol.js.map +1 -0
  192. package/dist/feedback/redact.d.ts +34 -0
  193. package/dist/feedback/redact.d.ts.map +1 -0
  194. package/dist/feedback/redact.js +258 -0
  195. package/dist/feedback/redact.js.map +1 -0
  196. package/dist/feedback/report.d.ts +51 -0
  197. package/dist/feedback/report.d.ts.map +1 -0
  198. package/dist/feedback/report.js +122 -0
  199. package/dist/feedback/report.js.map +1 -0
  200. package/dist/feedback/run.d.ts +21 -0
  201. package/dist/feedback/run.d.ts.map +1 -0
  202. package/dist/feedback/run.js +578 -0
  203. package/dist/feedback/run.js.map +1 -0
  204. package/dist/feedback/store.d.ts +24 -0
  205. package/dist/feedback/store.d.ts.map +1 -0
  206. package/dist/feedback/store.js +117 -0
  207. package/dist/feedback/store.js.map +1 -0
  208. package/dist/main.d.ts +6 -0
  209. package/dist/main.d.ts.map +1 -1
  210. package/dist/main.js +86 -5
  211. package/dist/main.js.map +1 -1
  212. package/dist/node-version.d.ts +13 -0
  213. package/dist/node-version.d.ts.map +1 -0
  214. package/dist/node-version.js +37 -0
  215. package/dist/node-version.js.map +1 -0
  216. package/dist/parse.d.ts +8 -2
  217. package/dist/parse.d.ts.map +1 -1
  218. package/dist/parse.js +7 -2
  219. package/dist/parse.js.map +1 -1
  220. package/dist/project-ref.d.ts +44 -0
  221. package/dist/project-ref.d.ts.map +1 -0
  222. package/dist/project-ref.js +69 -0
  223. package/dist/project-ref.js.map +1 -0
  224. package/dist/sdk-skills/kindgi-authoring-agents/SKILL.md +15 -2
  225. package/dist/sdk-skills/kindgi-authoring-flows/SKILL.md +1 -1
  226. package/dist/sdk-skills/kindgi-authoring-guardrails/SKILL.md +44 -7
  227. package/dist/sdk-skills/kindgi-authoring-mcp-servers/SKILL.md +11 -2
  228. package/dist/sdk-skills/kindgi-authoring-providers/SKILL.md +60 -13
  229. package/dist/sdk-skills/kindgi-authoring-tools/SKILL.md +19 -2
  230. package/dist/sdk-skills/kindgi-framework-feedback/SKILL.md +82 -3
  231. package/dist/sdk-skills/kindgi-getting-started/SKILL.md +1 -1
  232. package/dist/sdk-skills/kindgi-java-authoring-agents/SKILL.md +17 -3
  233. package/dist/sdk-skills/kindgi-java-authoring-flows/SKILL.md +1 -1
  234. package/dist/sdk-skills/kindgi-java-authoring-guardrails/SKILL.md +43 -6
  235. package/dist/sdk-skills/kindgi-java-authoring-tools/SKILL.md +19 -2
  236. package/dist/sdk-skills/kindgi-java-getting-started/SKILL.md +1 -1
  237. package/dist/sdk-skills/kindgi-python-authoring-agents/SKILL.md +17 -3
  238. package/dist/sdk-skills/kindgi-python-authoring-flows/SKILL.md +1 -1
  239. package/dist/sdk-skills/kindgi-python-authoring-guardrails/SKILL.md +49 -13
  240. package/dist/sdk-skills/kindgi-python-authoring-tools/SKILL.md +27 -3
  241. package/dist/sdk-skills/kindgi-python-getting-started/SKILL.md +1 -1
  242. package/dist/sdk-skills/kindgi-scala-authoring-agents/SKILL.md +17 -3
  243. package/dist/sdk-skills/kindgi-scala-authoring-flows/SKILL.md +1 -1
  244. package/dist/sdk-skills/kindgi-scala-authoring-guardrails/SKILL.md +43 -6
  245. package/dist/sdk-skills/kindgi-scala-authoring-tools/SKILL.md +19 -2
  246. package/dist/sdk-skills/kindgi-scala-getting-started/SKILL.md +1 -1
  247. package/dist/sdk-skills/kindgi-using/SKILL.md +1 -1
  248. package/dist/slug.d.ts +18 -0
  249. package/dist/slug.d.ts.map +1 -0
  250. package/dist/slug.js +29 -0
  251. package/dist/slug.js.map +1 -0
  252. package/dist/templates/drupal/AGENTS.md +2 -0
  253. package/dist/templates/java/AGENTS.md +2 -0
  254. package/dist/templates/minimal/AGENTS.md +2 -0
  255. package/dist/templates/python/AGENTS.md +2 -0
  256. package/dist/templates/sample/AGENTS.md +2 -0
  257. package/dist/templates/scala/AGENTS.md +2 -0
  258. package/dist/templates/woocommerce/AGENTS.md +11 -4
  259. package/dist/templates/woocommerce/README.md.tmpl +47 -4
  260. package/dist/templates/woocommerce/agents/store-agent/index.test.ts.tmpl +13 -0
  261. package/dist/templates/woocommerce/agents/store-agent/index.ts.tmpl +11 -1
  262. package/dist/templates/woocommerce/tools/publish-product/index.ts.tmpl +7 -1
  263. package/dist/templates/woocommerce/tools/refund/index.ts.tmpl +7 -2
  264. package/dist/templates/woocommerce/tools/refund-large/index.ts.tmpl +8 -2
  265. package/dist/templates/woocommerce/tools/set-price/index.ts.tmpl +6 -0
  266. package/dist/value-target.d.ts +139 -0
  267. package/dist/value-target.d.ts.map +1 -0
  268. package/dist/value-target.js +231 -0
  269. package/dist/value-target.js.map +1 -0
  270. package/package.json +13 -13
@@ -0,0 +1,111 @@
1
+ /**
2
+ * The feedback intake's wire, the CLI's side: Kindgi's intake on
3
+ * access.kindgi.com takes reports from `kindgi feedback submit`, answers
4
+ * `status`, and takes a report back on `withdraw`. All three are
5
+ * unauthenticated JSON POSTs, so a credential is never in a URL.
6
+ *
7
+ * - **`POST /feedback/reports`** takes the client's environment and 1 to 20
8
+ * entries, and answers each entry's `reportId` (not a credential: it goes
9
+ * in `FEEDBACK.md`) and `withdrawKey` (the only credential: kept in
10
+ * `~/.kindgi/feedback/keys.json`, never printed).
11
+ * - **`POST /feedback/reports/status`** takes up to 50 `reportId`s.
12
+ * - **`POST /feedback/reports/withdraw`** takes up to 50 `reportId`s, each
13
+ * with its `withdrawKey`.
14
+ *
15
+ * The caps here are the service's own, checked before anything is sent,
16
+ * so a report is never cut short and never refused for size after the
17
+ * person said yes. The service checks them again and refuses any other
18
+ * key, so a CLI that sent more would be refused, not stored.
19
+ */
20
+ import type { DoctorCheckId } from '../commands/doctor.js';
21
+ import type { FeedbackKind, FeedbackSeverity } from './entries.js';
22
+ export declare const FEEDBACK_REPORTS_PATH = "/feedback/reports";
23
+ export declare const FEEDBACK_STATUS_PATH = "/feedback/reports/status";
24
+ export declare const FEEDBACK_WITHDRAW_PATH = "/feedback/reports/withdraw";
25
+ /** A request body's limit, in bytes. */
26
+ export declare const MAX_REQUEST_BYTES: number;
27
+ export declare const MAX_ENTRIES = 20;
28
+ export declare const MAX_TITLE_LENGTH = 200;
29
+ /** An entry body's limit, in UTF-8 bytes. */
30
+ export declare const MAX_BODY_BYTES: number;
31
+ export declare const MAX_CHECKS = 32;
32
+ /** How many reports one status or withdraw request asks about. */
33
+ export declare const MAX_REPORT_IDS = 50;
34
+ export declare const REPORT_ID: RegExp;
35
+ export declare const WITHDRAW_KEY: RegExp;
36
+ export declare const ENTRY_ID: RegExp;
37
+ export declare const ENTRY_HASH: RegExp;
38
+ export declare const VERSION: RegExp;
39
+ export declare const MAX_VERSION_LENGTH = 64;
40
+ export declare const DATE: RegExp;
41
+ export declare const OS: RegExp;
42
+ export declare const OS_RELEASE: RegExp;
43
+ export declare const ARCH: RegExp;
44
+ export declare const MAX_ISSUE_URL_LENGTH = 500;
45
+ export declare const MAX_REASON_LENGTH = 200;
46
+ export type CheckStatus = 'pass' | 'warn' | 'fail' | 'skip';
47
+ export type ProjectLanguage = 'node' | 'python' | 'java' | 'scala';
48
+ export type AuthoredBy = 'claude-code' | 'human' | 'mixed';
49
+ /** What the CLI says about where it runs: never a path, a URL or a check's text. */
50
+ export interface ClientInfo {
51
+ readonly cli: string;
52
+ readonly os: string;
53
+ readonly osRelease: string;
54
+ readonly arch: string;
55
+ readonly node: string;
56
+ readonly language: ProjectLanguage | null;
57
+ readonly checks: readonly {
58
+ readonly id: DoctorCheckId;
59
+ readonly status: CheckStatus;
60
+ }[];
61
+ }
62
+ /** One entry as sent: its title and body after redaction. */
63
+ export interface EntryPayload {
64
+ readonly entry: string;
65
+ readonly hash: string;
66
+ readonly title: string;
67
+ readonly kind: FeedbackKind;
68
+ readonly severity: FeedbackSeverity;
69
+ readonly by: AuthoredBy;
70
+ readonly date: string;
71
+ readonly sdk: string;
72
+ readonly cli: string;
73
+ readonly body: string;
74
+ }
75
+ export interface SubmitPayload {
76
+ readonly client: ClientInfo;
77
+ readonly entries: readonly EntryPayload[];
78
+ }
79
+ export interface SubmittedReport {
80
+ readonly entry: string;
81
+ readonly reportId: string;
82
+ readonly withdrawKey: string;
83
+ }
84
+ export declare const REPORT_STATES: readonly ["received", "known", "fixed", "wont-fix", "withdrawn", "unknown"];
85
+ export type ReportState = (typeof REPORT_STATES)[number];
86
+ /** A state the report never leaves: `status` stops asking about it. */
87
+ export declare const FINAL_STATES: ReadonlySet<ReportState>;
88
+ export interface ReportStatus {
89
+ readonly reportId: string;
90
+ readonly state: ReportState;
91
+ readonly issueUrl?: string;
92
+ readonly fixedIn?: string;
93
+ readonly reason?: string;
94
+ }
95
+ export interface WithdrawAnswer {
96
+ readonly withdrawn: readonly string[];
97
+ readonly refused: readonly string[];
98
+ }
99
+ /** A version as the wire takes it: semver, at most 64 characters. */
100
+ export declare function isVersion(value: string): boolean;
101
+ /**
102
+ * The submit answer, checked against what was sent: one report per entry,
103
+ * in the request's order, each with a well-formed id and key. Anything
104
+ * else is `undefined`, and nothing is written.
105
+ */
106
+ export declare function readSubmitAnswer(body: unknown, sent: readonly EntryPayload[]): readonly SubmittedReport[] | undefined;
107
+ /** The status answer: one per id asked, in order, each with the fields its state allows. */
108
+ export declare function readStatusAnswer(body: unknown, asked: readonly string[]): readonly ReportStatus[] | undefined;
109
+ /** The withdraw answer: every id asked in exactly one of the two lists. */
110
+ export declare function readWithdrawAnswer(body: unknown, asked: readonly string[]): WithdrawAnswer | undefined;
111
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/feedback/protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,143 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+ export const FEEDBACK_REPORTS_PATH = '/feedback/reports';
4
+ export const FEEDBACK_STATUS_PATH = '/feedback/reports/status';
5
+ export const FEEDBACK_WITHDRAW_PATH = '/feedback/reports/withdraw';
6
+ /** A request body's limit, in bytes. */
7
+ export const MAX_REQUEST_BYTES = 64 * 1024;
8
+ export const MAX_ENTRIES = 20;
9
+ export const MAX_TITLE_LENGTH = 200;
10
+ /** An entry body's limit, in UTF-8 bytes. */
11
+ export const MAX_BODY_BYTES = 16 * 1024;
12
+ export const MAX_CHECKS = 32;
13
+ /** How many reports one status or withdraw request asks about. */
14
+ export const MAX_REPORT_IDS = 50;
15
+ export const REPORT_ID = /^fbr_[A-Za-z0-9_-]{16}$/;
16
+ export const WITHDRAW_KEY = /^kgi_fw_[A-Za-z0-9_-]{22}$/;
17
+ export const ENTRY_ID = /^\d{4}-\d{2}-\d{2}\.[1-9]\d{0,3}$/;
18
+ export const ENTRY_HASH = /^feedback-[0-9a-f]{8}$/;
19
+ export const VERSION = /^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$/;
20
+ export const MAX_VERSION_LENGTH = 64;
21
+ export const DATE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,3})?Z$/;
22
+ export const OS = /^[a-z0-9]{1,16}$/;
23
+ export const OS_RELEASE = /^[A-Za-z0-9._+-]{1,64}$/;
24
+ export const ARCH = /^[a-z0-9_]{1,16}$/;
25
+ export const MAX_ISSUE_URL_LENGTH = 500;
26
+ export const MAX_REASON_LENGTH = 200;
27
+ export const REPORT_STATES = [
28
+ 'received',
29
+ 'known',
30
+ 'fixed',
31
+ 'wont-fix',
32
+ 'withdrawn',
33
+ 'unknown',
34
+ ];
35
+ /** A state the report never leaves: `status` stops asking about it. */
36
+ export const FINAL_STATES = new Set(['fixed', 'wont-fix', 'withdrawn']);
37
+ /** A version as the wire takes it: semver, at most 64 characters. */
38
+ export function isVersion(value) {
39
+ return value.length <= MAX_VERSION_LENGTH && VERSION.test(value);
40
+ }
41
+ /**
42
+ * The submit answer, checked against what was sent: one report per entry,
43
+ * in the request's order, each with a well-formed id and key. Anything
44
+ * else is `undefined`, and nothing is written.
45
+ */
46
+ export function readSubmitAnswer(body, sent) {
47
+ const reports = recordOf(body)?.reports;
48
+ if (!Array.isArray(reports) || reports.length !== sent.length)
49
+ return undefined;
50
+ const out = [];
51
+ for (const [i, raw] of reports.entries()) {
52
+ const r = recordOf(raw);
53
+ const entry = sent[i]?.entry;
54
+ if (r === undefined ||
55
+ entry === undefined ||
56
+ r.entry !== entry ||
57
+ typeof r.reportId !== 'string' ||
58
+ !REPORT_ID.test(r.reportId) ||
59
+ typeof r.withdrawKey !== 'string' ||
60
+ !WITHDRAW_KEY.test(r.withdrawKey)) {
61
+ return undefined;
62
+ }
63
+ out.push({ entry, reportId: r.reportId, withdrawKey: r.withdrawKey });
64
+ }
65
+ return new Set(out.map((r) => r.reportId)).size === out.length ? out : undefined;
66
+ }
67
+ /** The status answer: one per id asked, in order, each with the fields its state allows. */
68
+ export function readStatusAnswer(body, asked) {
69
+ const reports = recordOf(body)?.reports;
70
+ if (!Array.isArray(reports) || reports.length !== asked.length)
71
+ return undefined;
72
+ const out = [];
73
+ for (const [i, raw] of reports.entries()) {
74
+ const r = recordOf(raw);
75
+ const reportId = asked[i];
76
+ if (r === undefined || reportId === undefined || r.reportId !== reportId)
77
+ return undefined;
78
+ const state = r.state;
79
+ if (typeof state !== 'string' || !REPORT_STATES.includes(state)) {
80
+ return undefined;
81
+ }
82
+ const status = {
83
+ reportId,
84
+ state: state,
85
+ };
86
+ if (r.issueUrl !== undefined) {
87
+ if ((state !== 'known' && state !== 'fixed') || !isIssueUrl(r.issueUrl))
88
+ return undefined;
89
+ status.issueUrl = r.issueUrl;
90
+ }
91
+ if (r.fixedIn !== undefined) {
92
+ if (state !== 'fixed' || typeof r.fixedIn !== 'string' || !isVersion(r.fixedIn)) {
93
+ return undefined;
94
+ }
95
+ status.fixedIn = r.fixedIn;
96
+ }
97
+ if (r.reason !== undefined) {
98
+ if (state !== 'wont-fix' ||
99
+ typeof r.reason !== 'string' ||
100
+ r.reason.length === 0 ||
101
+ r.reason.length > MAX_REASON_LENGTH) {
102
+ return undefined;
103
+ }
104
+ status.reason = r.reason;
105
+ }
106
+ out.push(status);
107
+ }
108
+ return out;
109
+ }
110
+ /** The withdraw answer: every id asked in exactly one of the two lists. */
111
+ export function readWithdrawAnswer(body, asked) {
112
+ const r = recordOf(body);
113
+ const withdrawn = r?.withdrawn;
114
+ const refused = r?.refused;
115
+ if (!isStringList(withdrawn) || !isStringList(refused))
116
+ return undefined;
117
+ const answered = [...withdrawn, ...refused];
118
+ const want = new Set(asked);
119
+ if (answered.length !== want.size || new Set(answered).size !== answered.length)
120
+ return undefined;
121
+ if (!answered.every((id) => want.has(id)))
122
+ return undefined;
123
+ return { withdrawn, refused };
124
+ }
125
+ function isIssueUrl(value) {
126
+ if (typeof value !== 'string' || value.length > MAX_ISSUE_URL_LENGTH)
127
+ return false;
128
+ try {
129
+ return new URL(value).protocol === 'https:';
130
+ }
131
+ catch {
132
+ return false;
133
+ }
134
+ }
135
+ function isStringList(value) {
136
+ return Array.isArray(value) && value.every((v) => typeof v === 'string');
137
+ }
138
+ function recordOf(value) {
139
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
140
+ ? value
141
+ : undefined;
142
+ }
143
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/feedback/protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /** What a redacted path, and a redacted email, read as. */
2
+ export declare const REDACTED_PATH = "[path]";
3
+ export declare const REDACTED_EMAIL = "[email]";
4
+ /** The rules, in the order they run. */
5
+ export declare const REDACTION_RULES: readonly ["private-keys", "env-values", "tokens", "urls", "emails", "paths"];
6
+ export type RedactionRule = (typeof REDACTION_RULES)[number];
7
+ export interface EnvEntry {
8
+ readonly key: string;
9
+ readonly value: string;
10
+ }
11
+ export interface RedactionContext {
12
+ /** The pack's directory, absolute. */
13
+ readonly packDir: string;
14
+ /** The home directory, absolute. */
15
+ readonly home: string;
16
+ /** Every entry in the pack's env files (`readPackEnvEntries`). */
17
+ readonly envEntries: readonly EnvEntry[];
18
+ }
19
+ export interface Redacted {
20
+ readonly text: string;
21
+ /** The rules that changed something, in the order they ran. */
22
+ readonly applied: readonly RedactionRule[];
23
+ }
24
+ /**
25
+ * Every entry in the pack's env files: each `.env*` file at its root, the
26
+ * `dev.envFiles` given (relative to the pack), and Kindgi's own
27
+ * `.kindgi/secrets.env`. It takes every file's entries, not just the ones
28
+ * that win, since a value a later file overrides is still a secret. A
29
+ * missing or unreadable file is skipped.
30
+ */
31
+ export declare function readPackEnvEntries(packDir: string, envFiles?: readonly string[]): Promise<readonly EnvEntry[]>;
32
+ /** The text with every rule applied (see the header), and which rules changed it. */
33
+ export declare function redactForSending(text: string, ctx: RedactionContext): Redacted;
34
+ //# sourceMappingURL=redact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/feedback/redact.ts"],"names":[],"mappings":"AA+CA,2DAA2D;AAC3D,eAAO,MAAM,aAAa,WAAW,CAAC;AACtC,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC,wCAAwC;AACxC,eAAO,MAAM,eAAe,8EAOlB,CAAC;AACX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,sCAAsC;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,oCAAoC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,SAAS,QAAQ,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;CAC5C;AAKD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,SAAS,MAAM,EAAO,GAC/B,OAAO,CAAC,SAAS,QAAQ,EAAE,CAAC,CAkB9B;AAED,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,gBAAgB,GAAG,QAAQ,CAe9E"}
@@ -0,0 +1,258 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+ /**
4
+ * What `kindgi feedback submit` takes out of a report's text before the
5
+ * person previews it, so the preview shows what would be sent. It cuts
6
+ * down what the person has to catch. It can't promise free text is clean:
7
+ * the preview is the guarantee. The rules run in this order:
8
+ *
9
+ * 1. **Private keys.** A `-----BEGIN … PRIVATE KEY-----` block, to its
10
+ * `END` line or the end of the text, becomes `[redacted]`.
11
+ * 2. **The pack's env values.** Each value in the pack's env files
12
+ * (`readPackEnvEntries`) becomes `[redacted]` wherever it appears.
13
+ * That's a value of 8 characters or more, or of 4 or more under a key
14
+ * that looks secret (`isSecretKey`). A shorter one (`PORT=3000`) stays,
15
+ * so the text stays readable.
16
+ * 3. **Tokens.** First, the shapes `@kindgi/log` masks in every log line
17
+ * (`scrubText`): a Kindgi token keeps its prefix and last four
18
+ * characters, `Bearer …` and a URL's password are masked. Then
19
+ * provider and cloud keys by their shape (`sk-…`, `AKIA…`, `ghp_…`,
20
+ * `xoxb-…`, `AIza…`, a JWT, …), and the value under a key that looks
21
+ * secret: `KEY=…`, `--api-key=…`, `"token": "…"`, and a whole
22
+ * `Authorization: …` line.
23
+ * 4. **URLs.** A URL's user info, and each of its query values.
24
+ * 5. **Emails** become `[email]`.
25
+ * 6. **Paths.**
26
+ * - One inside the pack becomes relative to it (`./src/tool.ts`).
27
+ * - The home directory becomes `~`.
28
+ * - Any other absolute path becomes `[path]`: one under `~`, under a
29
+ * filesystem root such as `/Users`, `/home` or `/tmp`, after a drive
30
+ * letter, or on a UNC share. A path that doesn't start at one of
31
+ * those, like an API route (`/v1/secrets`), stays.
32
+ * - A path is cut at a space, and the preview shows what follows it.
33
+ *
34
+ * Nothing here reads a file or the environment: `redactForSending` takes
35
+ * the pack's directory, the home directory and the env entries from its
36
+ * caller, so the same text and context always give the same result (and
37
+ * the digest the person OKs stays stable).
38
+ */
39
+ import { readFile, readdir } from 'node:fs/promises';
40
+ import { join } from 'node:path';
41
+ import { REDACTED, isSecretKey, scrubText } from '@kindgi/log';
42
+ import { parseEnvFile } from '../env/parser.js';
43
+ /** What a redacted path, and a redacted email, read as. */
44
+ export const REDACTED_PATH = '[path]';
45
+ export const REDACTED_EMAIL = '[email]';
46
+ /** The rules, in the order they run. */
47
+ export const REDACTION_RULES = [
48
+ 'private-keys',
49
+ 'env-values',
50
+ 'tokens',
51
+ 'urls',
52
+ 'emails',
53
+ 'paths',
54
+ ];
55
+ /** Kindgi's own secrets file in a pack, which `kindgi secrets set` writes. */
56
+ const KINDGI_SECRETS_FILE = '.kindgi/secrets.env';
57
+ /**
58
+ * Every entry in the pack's env files: each `.env*` file at its root, the
59
+ * `dev.envFiles` given (relative to the pack), and Kindgi's own
60
+ * `.kindgi/secrets.env`. It takes every file's entries, not just the ones
61
+ * that win, since a value a later file overrides is still a secret. A
62
+ * missing or unreadable file is skipped.
63
+ */
64
+ export async function readPackEnvEntries(packDir, envFiles = []) {
65
+ const atRoot = await readdir(packDir, { withFileTypes: true }).catch(() => []);
66
+ const files = new Set([
67
+ ...atRoot.filter((e) => e.isFile() && e.name.startsWith('.env')).map((e) => e.name),
68
+ ...envFiles,
69
+ KINDGI_SECRETS_FILE,
70
+ ]);
71
+ const entries = [];
72
+ for (const file of [...files].sort()) {
73
+ const raw = await readFile(join(packDir, file), 'utf8').catch(() => undefined);
74
+ if (raw === undefined)
75
+ continue;
76
+ for (const line of parseEnvFile(raw)) {
77
+ if (line.kind === 'entry' && line.key !== undefined && line.value !== undefined) {
78
+ entries.push({ key: line.key, value: line.value });
79
+ }
80
+ }
81
+ }
82
+ return entries;
83
+ }
84
+ /** The text with every rule applied (see the header), and which rules changed it. */
85
+ export function redactForSending(text, ctx) {
86
+ const applied = [];
87
+ let out = text;
88
+ const step = (rule, apply) => {
89
+ const next = apply(out);
90
+ if (next !== out)
91
+ applied.push(rule);
92
+ out = next;
93
+ };
94
+ step('private-keys', (s) => s.replace(PRIVATE_KEY_BLOCK, REDACTED));
95
+ step('env-values', (s) => redactEnvValues(s, ctx.envEntries));
96
+ step('tokens', redactTokens);
97
+ step('urls', (s) => s.replace(URL_IN_TEXT, redactUrl));
98
+ step('emails', (s) => s.replace(EMAIL, REDACTED_EMAIL));
99
+ step('paths', (s) => redactPaths(s, ctx));
100
+ return { text: out, applied };
101
+ }
102
+ const PRIVATE_KEY_BLOCK = /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?(?:-----END [A-Z0-9 ]*PRIVATE KEY-----|$)/g;
103
+ const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
104
+ /** A value that already stands for something else: nothing to redact. */
105
+ const isPlaceholder = (value) => value === '' || value === REDACTED || /^(?:\$|<|\*\*\*)/.test(value);
106
+ function redactEnvValues(text, entries) {
107
+ const values = new Set();
108
+ for (const { key, value } of entries) {
109
+ if (isPlaceholder(value))
110
+ continue;
111
+ if (value.length >= 8 || (value.length >= 4 && isSecretKey(key)))
112
+ values.add(value);
113
+ }
114
+ // The longest first, so a value that holds a shorter one goes whole.
115
+ let out = text;
116
+ for (const value of [...values].sort((a, b) => b.length - a.length)) {
117
+ out = out.replace(new RegExp(escapeRegExp(value), 'g'), REDACTED);
118
+ }
119
+ return out;
120
+ }
121
+ /** Provider and cloud keys, by the shapes their issuers give them. */
122
+ const PROVIDER_KEYS = [
123
+ // OpenAI, Anthropic, OpenRouter and others: `sk-`, `sk-proj-`, `sk-ant-`, `sk-or-v1-`.
124
+ /\bsk-[A-Za-z0-9_-]{20,}/g,
125
+ // AWS access key ids.
126
+ /\b(?:AKIA|ASIA|AGPA|AIDA|AROA|ANPA|ANVA|AIPA)[A-Z0-9]{16}\b/g,
127
+ // GitHub tokens.
128
+ /\bgh[pousr]_[A-Za-z0-9]{36,}\b/g,
129
+ /\bgithub_pat_[A-Za-z0-9_]{22,}\b/g,
130
+ // Slack tokens.
131
+ /\bxox[abposr]-[A-Za-z0-9-]{10,}/g,
132
+ // Google API keys.
133
+ /\bAIza[0-9A-Za-z_-]{35}/g,
134
+ // Stripe keys.
135
+ /\b(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{16,}\b/g,
136
+ // SendGrid keys.
137
+ /\bSG\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}/g,
138
+ // Hugging Face tokens.
139
+ /\bhf_[A-Za-z0-9]{30,}\b/g,
140
+ // A JWT: three base64url parts, the first two JSON objects.
141
+ /\beyJ[A-Za-z0-9_-]{8,}\.eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g,
142
+ ];
143
+ /** `"key": "value"`, in JSON. */
144
+ const JSON_PAIR = /"([^"\\\n]{1,100})"(\s*:\s*)"((?:[^"\\\n]|\\.)*)"/g;
145
+ /** `KEY=value`, `--key=value`, `key = "value"`. */
146
+ const ASSIGNMENT = /(?<![\w.])([A-Za-z_][\w.-]*)(\s*=\s*)(?:"([^"\n]*)"|'([^'\n]*)'|([^\s"'`,;&]+))/g;
147
+ /** `Key: value` starting a line, as in YAML or an HTTP header: the rest of the line. */
148
+ const LINE_PAIR = /^([ \t]*)([A-Za-z_][\w.-]*)([ \t]*:[ \t]+)(\S.*)$/gm;
149
+ /** An Azure connection string's key. */
150
+ const AZURE_KEY = /\b(AccountKey|SharedAccessKey)=[^;\s"']+/g;
151
+ function redactTokens(text) {
152
+ let out = scrubText(text);
153
+ for (const shape of PROVIDER_KEYS)
154
+ out = out.replace(shape, REDACTED);
155
+ out = out.replace(AZURE_KEY, `$1=${REDACTED}`);
156
+ out = out.replace(JSON_PAIR, (m, key, colon, value) => isSecretKey(key) && !isPlaceholder(value) ? `"${key}"${colon}"${REDACTED}"` : m);
157
+ out = out.replace(ASSIGNMENT, (m, key, eq, dq, sq, bare) => {
158
+ const value = dq ?? sq ?? bare ?? '';
159
+ if (!isSecretKey(key) || isPlaceholder(value))
160
+ return m;
161
+ const quote = dq !== undefined ? '"' : sq !== undefined ? "'" : '';
162
+ return `${key}${eq}${quote}${REDACTED}${quote}`;
163
+ });
164
+ out = out.replace(LINE_PAIR, (m, indent, key, colon, value) => isSecretKey(key) && !isPlaceholder(value) ? `${indent}${key}${colon}${REDACTED}` : m);
165
+ return out;
166
+ }
167
+ const URL_IN_TEXT = /\b([a-z][a-z0-9+.-]*:\/\/)([^\s"'<>`]+)/gi;
168
+ /** A URL with its user info and each query value redacted. */
169
+ function redactUrl(_m, scheme, rest) {
170
+ const at = rest.search(/[/?#]/);
171
+ const authority = at === -1 ? rest : rest.slice(0, at);
172
+ let tail = at === -1 ? '' : rest.slice(at);
173
+ const userinfo = authority.lastIndexOf('@');
174
+ const host = userinfo === -1 ? authority : `${REDACTED}@${authority.slice(userinfo + 1)}`;
175
+ const q = tail.indexOf('?');
176
+ if (q !== -1) {
177
+ const hash = tail.indexOf('#', q);
178
+ const query = tail.slice(q + 1, hash === -1 ? undefined : hash);
179
+ const redacted = query
180
+ .split('&')
181
+ .map((pair) => {
182
+ if (pair === '')
183
+ return pair;
184
+ const eq = pair.indexOf('=');
185
+ return eq === -1 ? REDACTED : `${pair.slice(0, eq)}=${REDACTED}`;
186
+ })
187
+ .join('&');
188
+ tail = `${tail.slice(0, q + 1)}${redacted}${hash === -1 ? '' : tail.slice(hash)}`;
189
+ }
190
+ return `${scheme}${host}${tail}`;
191
+ }
192
+ const EMAIL = /(?<![\w.%+-])[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}\b/g;
193
+ /** The characters a path runs through: it stops at a space, a quote, a bracket or a colon. */
194
+ const PATH_CHARS = '[^\\s"\'`<>|:;,()\\[\\]{}]*';
195
+ /** A separator: `/`, `\`, or `\\` (a backslash in JSON). */
196
+ const SEP = '(\\\\\\\\|[\\\\/])';
197
+ /** The roots an absolute POSIX path starts at, as far as a report goes. */
198
+ const POSIX_ROOTS = [
199
+ 'Users',
200
+ 'home',
201
+ 'root',
202
+ 'private',
203
+ 'tmp',
204
+ 'var',
205
+ 'opt',
206
+ 'etc',
207
+ 'mnt',
208
+ 'media',
209
+ 'Volumes',
210
+ 'srv',
211
+ 'usr',
212
+ 'nix',
213
+ 'workspace',
214
+ 'workspaces',
215
+ 'data',
216
+ 'app',
217
+ 'run',
218
+ 'snap',
219
+ 'Library',
220
+ 'Applications',
221
+ 'System',
222
+ ];
223
+ const TILDE_PATH = new RegExp(`(?<![\\w.-])~${SEP}${PATH_CHARS}`, 'g');
224
+ const POSIX_PATH = new RegExp(`(?<![\\w.~-])/(?:${POSIX_ROOTS.join('|')})(?![\\w.-])(?:/${PATH_CHARS})?`, 'g');
225
+ const DRIVE_PATH = new RegExp(`(?<![\\w])[A-Za-z]:${SEP}${PATH_CHARS}`, 'g');
226
+ const UNC_PATH = new RegExp(`(?<![\\w\\\\])\\\\\\\\[\\w.$-]+\\\\${PATH_CHARS}`, 'g');
227
+ const isWindowsPath = (dir) => /^(?:[A-Za-z]:[\\/]|\\\\)/.test(dir);
228
+ /** The ways a directory can be written in text: as given, with either separator, and JSON-escaped. */
229
+ function spellings(dir) {
230
+ const trimmed = dir.replace(/[\\/]+$/, '');
231
+ if (trimmed === '')
232
+ return [];
233
+ if (!isWindowsPath(trimmed))
234
+ return [trimmed];
235
+ const back = trimmed.replace(/\//g, '\\');
236
+ return [...new Set([back, back.replace(/\\/g, '/'), back.replace(/\\/g, '\\\\')])];
237
+ }
238
+ /** `dir` replaced by `to`, at path boundaries: `to` alone for the directory, `to<sep>` before a path in it. */
239
+ function replaceDir(text, dir, to) {
240
+ let out = text;
241
+ // The longest spelling first: the JSON-escaped one holds the others' prefixes.
242
+ for (const spelling of spellings(dir).sort((a, b) => b.length - a.length)) {
243
+ const flags = isWindowsPath(spelling) ? 'gi' : 'g';
244
+ const re = new RegExp(`(?<![\\w.-])${escapeRegExp(spelling)}(?:${SEP}|(?![\\w.-]))`, flags);
245
+ out = out.replace(re, (_m, sep) => sep === undefined ? to : `${to}${sep}`);
246
+ }
247
+ return out;
248
+ }
249
+ function redactPaths(text, ctx) {
250
+ let out = replaceDir(text, ctx.packDir, '.');
251
+ out = replaceDir(out, ctx.home, '~');
252
+ return out
253
+ .replace(TILDE_PATH, REDACTED_PATH)
254
+ .replace(UNC_PATH, REDACTED_PATH)
255
+ .replace(DRIVE_PATH, REDACTED_PATH)
256
+ .replace(POSIX_PATH, REDACTED_PATH);
257
+ }
258
+ //# sourceMappingURL=redact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/feedback/redact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import type { DoctorReport } from '../commands/doctor.js';
2
+ import { type FeedbackEntry } from './entries.js';
3
+ import { type ClientInfo, type EntryPayload, type SubmitPayload } from './protocol.js';
4
+ import { type RedactionContext, type RedactionRule } from './redact.js';
5
+ /** Where the CLI runs, as the payload says it. */
6
+ export interface Platform {
7
+ readonly os: string;
8
+ readonly osRelease: string;
9
+ readonly arch: string;
10
+ readonly node: string;
11
+ }
12
+ /** An entry that can't be sent as it is, and why: named by its id, or its title without one. */
13
+ export interface EntryProblem {
14
+ readonly entry: string;
15
+ readonly problem: string;
16
+ }
17
+ /** The entries to send: those named, or with none named, every one not yet sent and not fixed. */
18
+ export declare function pickEntries(entries: readonly FeedbackEntry[], selectors: readonly string[]): {
19
+ readonly kind: 'ok';
20
+ readonly picked: readonly FeedbackEntry[];
21
+ } | {
22
+ readonly kind: 'unmatched';
23
+ readonly selectors: readonly string[];
24
+ };
25
+ /** The client's environment: the doctor's checks as id and status only, never their text. */
26
+ export declare function clientInfo(doctor: DoctorReport, platform: Platform): ClientInfo;
27
+ /** One entry as sent, its title and body redacted, or what stops it being sent. */
28
+ export declare function entryPayload(entry: FeedbackEntry, redaction: RedactionContext): {
29
+ readonly kind: 'ok';
30
+ readonly payload: EntryPayload;
31
+ readonly applied: readonly RedactionRule[];
32
+ } | {
33
+ readonly kind: 'problem';
34
+ readonly problem: EntryProblem;
35
+ };
36
+ /** The request body's bytes and their digest. */
37
+ export declare function serialize(payload: SubmitPayload): {
38
+ readonly bytes: string;
39
+ readonly digest: string;
40
+ };
41
+ /**
42
+ * The entries that fit one request: at most 20, at most 64 KiB in all, in
43
+ * the file's order. `held` is how many were left for the next run.
44
+ */
45
+ export declare function fitRequest(client: ClientInfo, entries: readonly EntryPayload[]): {
46
+ readonly entries: readonly EntryPayload[];
47
+ readonly held: number;
48
+ };
49
+ /** Whether a request with these entries fits: for entries the person named, which are never left out. */
50
+ export declare function fitsOneRequest(client: ClientInfo, entries: readonly EntryPayload[]): boolean;
51
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/feedback/report.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAW,KAAK,aAAa,EAAqB,MAAM,cAAc,CAAC;AAC9E,OAAO,EAGL,KAAK,UAAU,EAIf,KAAK,YAAY,EAQjB,KAAK,aAAa,EAEnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAEnB,MAAM,aAAa,CAAC;AAErB,kDAAkD;AAClD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,gGAAgG;AAChG,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,kGAAkG;AAClG,wBAAgB,WAAW,CACzB,OAAO,EAAE,SAAS,aAAa,EAAE,EACjC,SAAS,EAAE,SAAS,MAAM,EAAE,GAE1B;IAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAA;CAAE,GAClE;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAiBxE;AAED,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,GAAG,UAAU,CAU/E;AAED,mFAAmF;AACnF,wBAAgB,YAAY,CAC1B,KAAK,EAAE,aAAa,EACpB,SAAS,EAAE,gBAAgB,GAEzB;IACE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;CAC5C,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAAE,CAuD/D;AAED,iDAAiD;AACjD,wBAAgB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG;IACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAGA;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,SAAS,YAAY,EAAE,GAC/B;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAUtE;AAED,yGAAyG;AACzG,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,OAAO,CAK5F"}