@mmnto/totem 2.0.0 → 2.2.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 (67) hide show
  1. package/dist/compiler.d.ts +12 -0
  2. package/dist/compiler.d.ts.map +1 -1
  3. package/dist/compiler.js +17 -3
  4. package/dist/compiler.js.map +1 -1
  5. package/dist/config-schema.d.ts +28 -3
  6. package/dist/config-schema.d.ts.map +1 -1
  7. package/dist/config-schema.js +22 -3
  8. package/dist/config-schema.js.map +1 -1
  9. package/dist/config-schema.test.js +33 -0
  10. package/dist/config-schema.test.js.map +1 -1
  11. package/dist/describe.d.ts +19 -0
  12. package/dist/describe.d.ts.map +1 -1
  13. package/dist/describe.js +83 -12
  14. package/dist/describe.js.map +1 -1
  15. package/dist/describe.test.js +69 -2
  16. package/dist/describe.test.js.map +1 -1
  17. package/dist/gate-engine.d.ts +11 -1
  18. package/dist/gate-engine.d.ts.map +1 -1
  19. package/dist/gate-engine.js +27 -5
  20. package/dist/gate-engine.js.map +1 -1
  21. package/dist/gate-types.d.ts +17 -2
  22. package/dist/gate-types.d.ts.map +1 -1
  23. package/dist/index.d.ts +8 -4
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +5 -2
  26. package/dist/index.js.map +1 -1
  27. package/dist/parity-detect.d.ts +41 -4
  28. package/dist/parity-detect.d.ts.map +1 -1
  29. package/dist/parity-detect.js +264 -1
  30. package/dist/parity-detect.js.map +1 -1
  31. package/dist/parity-detect.orientation-rows.test.d.ts +17 -0
  32. package/dist/parity-detect.orientation-rows.test.d.ts.map +1 -0
  33. package/dist/parity-detect.orientation-rows.test.js +357 -0
  34. package/dist/parity-detect.orientation-rows.test.js.map +1 -0
  35. package/dist/parity-label-canon.d.ts +160 -0
  36. package/dist/parity-label-canon.d.ts.map +1 -0
  37. package/dist/parity-label-canon.js +220 -0
  38. package/dist/parity-label-canon.js.map +1 -0
  39. package/dist/parity-label-canon.test.d.ts +11 -0
  40. package/dist/parity-label-canon.test.d.ts.map +1 -0
  41. package/dist/parity-label-canon.test.js +296 -0
  42. package/dist/parity-label-canon.test.js.map +1 -0
  43. package/dist/parity-manifest.d.ts +9 -0
  44. package/dist/parity-manifest.d.ts.map +1 -1
  45. package/dist/parity-manifest.js +47 -0
  46. package/dist/parity-manifest.js.map +1 -1
  47. package/dist/parity-manifest.test.js +45 -0
  48. package/dist/parity-manifest.test.js.map +1 -1
  49. package/dist/recurrence-stats.d.ts +10 -10
  50. package/dist/retrospect.d.ts +42 -42
  51. package/dist/selection-manifest.d.ts +4 -4
  52. package/dist/selection-manifest.d.ts.map +1 -1
  53. package/dist/selection-manifest.js +2 -0
  54. package/dist/selection-manifest.js.map +1 -1
  55. package/dist/transport-shield.d.ts +190 -0
  56. package/dist/transport-shield.d.ts.map +1 -0
  57. package/dist/transport-shield.fold.test.d.ts +2 -0
  58. package/dist/transport-shield.fold.test.d.ts.map +1 -0
  59. package/dist/transport-shield.fold.test.js +439 -0
  60. package/dist/transport-shield.fold.test.js.map +1 -0
  61. package/dist/transport-shield.js +1040 -0
  62. package/dist/transport-shield.js.map +1 -0
  63. package/dist/transport-shield.test.d.ts +2 -0
  64. package/dist/transport-shield.test.d.ts.map +1 -0
  65. package/dist/transport-shield.test.js +298 -0
  66. package/dist/transport-shield.test.js.map +1 -0
  67. package/package.json +1 -1
@@ -0,0 +1,190 @@
1
+ import type { GateEvaluator } from './gate-types.js';
2
+ /**
3
+ * transport-shield (mmnto-ai/totem#2799): a PreToolUse gate over the Bash and
4
+ * PowerShell tools that refuses the KNOWN payload-mangling command shapes before
5
+ * the shell sees them, naming the cure in every refusal.
6
+ *
7
+ * The pattern table lives HERE, once, beside the evaluator (the charter's
8
+ * errata: provenance is the table in core; the CLI only installs). Every row is
9
+ * a pure function of the payload — no filesystem, no environment, no clock
10
+ * beyond the verdict's `checkedAt` — so the same command yields the same
11
+ * verdict on every machine given the same `platform` and `tool` fields, and a
12
+ * test can pin win32 on any runner.
13
+ *
14
+ * Evaluation order is the table order: the first DENY row that fires wins; a
15
+ * WARN row is consulted only when no deny fired. A shape the table lacks is
16
+ * allowed — the gate enumerates known shapes (the charter's positive corpus),
17
+ * and a miss is a corpus gap counted by the charter's metric, never a fail-open
18
+ * of an applicable gate.
19
+ *
20
+ * False-positive budget (ADR-109: a non-exact-match gate ships a stated budget
21
+ * and the fixture that measures it): ZERO denies over the benign corpus in
22
+ * `transport-shield.fold.test.ts` (everyday commands that share a token with a
23
+ * row — `diff -b`, `curl -b`, `grep gh -b`, a Windows path as a sed operand,
24
+ * `<<` inside a quoted argument, a here-string). A deny on a benign command in
25
+ * the field is a corpus row plus a fix, never a hand-carved exemption; the
26
+ * `--pilot` tier exists for a measurement week.
27
+ *
28
+ * Out of scope by design, disclosed: a bare backslash outside the four named
29
+ * contexts (a heredoc body, a sed -i expression, an inline node/python body, a
30
+ * gh --body) is not a shape this gate reads; a heredoc inside a `bash -c "…"`
31
+ * or `sh -c '…'` operand is quoted text to this scanner and is not recursed
32
+ * into (a corpus gap, not a fail-open of an applicable row); a wrapper that
33
+ * takes operands of its own before the program (`sudo -u me gh …`, `timeout
34
+ * 30 gh …`, `npx …`) hides the program from the position anchor — the same
35
+ * class. The scanners read the shell's own grammar where a mis-read would
36
+ * desynchronize them: a `#` that begins a word — after an unquoted blank,
37
+ * newline, `;`, `|`, `&`, an opening `(` or an OPERATOR `)` (a subshell's, a
38
+ * case pattern's) — is a comment to the end of the line, discarded WITHOUT
39
+ * quote processing (POSIX 2.3 rule 9; bash §3.1.3), while a `#` that continues
40
+ * a word is not one: `a#b`, and `$(x)#1` / `<(x)#1`, where the `)` closes a
41
+ * substitution that is part of the word (rules 5 and 8 for `$( … )`; process
42
+ * substitution is a bash extension, bash §3.5.6, that behaves the same way) —
43
+ * the scanners track which `(` each `)` closes. `$(( … ))` / `(( … ))` arithmetic is skipped. So
44
+ * neither an apostrophe in a comment nor a `<<` shift can hide a later heredoc
45
+ * or expose comment text as arguments. For the PowerShell tool the SAME walk
46
+ * reads PowerShell's grammar where it differs from bash's, so there is one
47
+ * model of which text is code and no pre-pass to disagree with it: a `<# … #>`
48
+ * block comment outside quotes is skipped whole (a `<#` inside a string is
49
+ * text; a quote inside a block opens nothing), the backtick is the escape
50
+ * inside a double-quoted string, and a `#` is read by the same word-boundary
51
+ * rule as bash's. Not read, disclosed: PowerShell also begins a comment after a
52
+ * token-ending string, an assignment operator or a `)` (`'a'#b`, `$x=#c`,
53
+ * `$(1)#c`), which the scanners read as word text — the over-scan direction,
54
+ * except when such a comment carries text the scanners read as shell syntax
55
+ * (an odd `'` or `"`, a `<#`, a trailing backslash, an unterminated `$(`) on
56
+ * the line before a later positive: those five carriers, each confirmed by
57
+ * execution, are the miss direction. PowerShell's token boundaries are not
58
+ * derivable from a character walk (`$x=#c` is an assignment and a comment at
59
+ * statement position but one argument after a command; `'a'#b` and `x='a'#c`
60
+ * differ only by where the token began), and five successive folds of the
61
+ * PowerShell reading — a pre-pass, its string tracking, its comment rule, then
62
+ * two token-boundary models inside the scanners — each opened a sibling shape
63
+ * (the bot-round record on mmnto-ai/totem#2804), so they stay disclosed rather
64
+ * than modelled. PowerShell
65
+ * here-strings (`@" … "@`, `@' … '@`) are not parsed either — a quote inside
66
+ * one can desynchronize the quote scan for that tool, the miss direction. The
67
+ * MSYS opt-out is honoured through the shell forms that export
68
+ * the variable to the judged program (MSYS reads its presence, any value): the
69
+ * segment's own `VAR=… prog` prefix, an earlier `export` / `declare -x` /
70
+ * `typeset -x`, a bare assignment under `set -a` or followed by `export NAME`,
71
+ * until an `unset` — never as a substring: a comment, a heredoc body or a
72
+ * quoted string that names the cure opts nothing out. Disclosed over-allow: an
73
+ * export inside a subshell `( … )` or a pipeline element is taken as reaching
74
+ * later segments though the shell would not apply it.
75
+ */
76
+ export declare const TRANSPORT_SHIELD_EVENT = "transport-shield";
77
+ /** The module label every verdict cites as its `provenance.source` (never a path). */
78
+ export declare const TRANSPORT_SHIELD_SOURCE = "transport-shield pattern table";
79
+ /** A heredoc body at or above this many bytes WARNs (the banked ~4 KB harness trap). */
80
+ export declare const HEREDOC_OVERSIZE_BYTES = 4096;
81
+ /** `provenance.matched` is bounded to this many characters. */
82
+ export declare const MATCHED_FRAGMENT_MAX = 80;
83
+ export type TransportTool = 'Bash' | 'PowerShell';
84
+ export interface TransportShieldPayload {
85
+ tool: TransportTool;
86
+ command: string;
87
+ /** The host's `process.platform` — REQUIRED so the verdict never reads it in core. */
88
+ platform: string;
89
+ }
90
+ export type TransportPatternId = 'heredoc-escape' | 'heredoc-oversize' | 'msys-body-slash' | 'sed-i-escape' | 'inline-body-escape' | 'msys-rev-path-subshell';
91
+ export interface TransportMatch {
92
+ /** The offending fragment, raw and as written; the evaluator bounds and sanitizes it for provenance. */
93
+ fragment: string;
94
+ /** One clause naming what matched, for the reason text. */
95
+ detail: string;
96
+ }
97
+ export interface TransportPattern {
98
+ id: TransportPatternId;
99
+ disposition: 'deny' | 'warn';
100
+ /** The safe alternative, in the imperative; joined to the detail in the reason. */
101
+ cure: string;
102
+ find(payload: TransportShieldPayload): TransportMatch | null;
103
+ }
104
+ /**
105
+ * Parse an unknown payload into the gate's shape. Throws `GATE_INVALID` on a
106
+ * missing or non-string `command`, a `tool` outside the pair, or a missing
107
+ * `platform` — never default-allows (ADR-109: an unparseable payload is a
108
+ * broken source). The distributed wrapper never sends such a payload: it exits
109
+ * 0 as not-applicable first, so this branch is reachable only by hand.
110
+ */
111
+ export declare function parseTransportShieldPayload(payload: unknown): TransportShieldPayload;
112
+ export interface HeredocSpan {
113
+ /** The delimiter word as written (quotes stripped). */
114
+ delimiter: string;
115
+ /** Whether the delimiter was quoted (`<<'EOF'` / `<<"EOF"`). */
116
+ quoted: boolean;
117
+ /** Whether the operator was `<<-` (bash strips leading TABS from body and terminator lines). */
118
+ stripTabs: boolean;
119
+ /** The body text between the operator line and the terminator line (or the end). */
120
+ body: string;
121
+ /** True when no terminator line was found — the body runs to the end of the command. */
122
+ unterminated: boolean;
123
+ /** Offsets of the body within the command, for blanking. */
124
+ bodyStart: number;
125
+ bodyEnd: number;
126
+ }
127
+ /**
128
+ * What the scanners read beyond bash's grammar. `powershell` (the PowerShell
129
+ * tool): a `<# … #>` block comment outside quotes is skipped whole (inside a
130
+ * `$( … )` too); the backtick is the escape inside a double-quoted string.
131
+ * Everything else — where a `#` begins a comment, what a quote or an `=` does
132
+ * to a token — is read with bash's rules; the shapes where PowerShell's
133
+ * tokenizer differs are disclosed in the module header, not modelled.
134
+ */
135
+ export interface ScanOptions {
136
+ powershell?: boolean;
137
+ }
138
+ /**
139
+ * Locate every heredoc in a command in ONE pass that tracks shell quoting and
140
+ * SKIPS heredoc bodies: an operator inside a quoted argument is text, `<<<` is
141
+ * a here-string, and an apostrophe inside a body never opens a quote (the
142
+ * fold's own regression, mmnto-ai/totem#2799 pass 2). A body starts after the
143
+ * newline that ends the operator's line and runs to the first line that IS the
144
+ * delimiter — an exact line match, as bash reads it (a `EOF ` with trailing
145
+ * space or a CRLF `EOF\r` does not terminate); for `<<-` leading tabs are
146
+ * stripped first — or to the end of the command when no such line exists. An
147
+ * operator with no newline after it yields a body of the remaining text: the
148
+ * conservative reading, so a truncated command still refuses on its escapes.
149
+ * A `#` that begins a word discards the rest of its line without quote
150
+ * processing, as bash does, and `$(( … ))` / `(( … ))` arithmetic is skipped.
151
+ * `parens` records what each open `(` is — a substitution (`$(`, `<(`, `>(`),
152
+ * which is part of a word, or a grouping operator — so the `)` that closes it
153
+ * can say whether the next character begins a word. With `powershell` set the
154
+ * same walk reads PowerShell's grammar where it differs (see `ScanOptions`).
155
+ */
156
+ export declare function findHeredocs(command: string, opts?: ScanOptions): HeredocSpan[];
157
+ export interface ShellSegment {
158
+ /**
159
+ * Tokens with quotes resolved: single-quoted text literal; inside double
160
+ * quotes a backslash escapes only `$`, backtick, `"`, `\` and newline (POSIX)
161
+ * and is otherwise kept; outside quotes a backslash escapes the next character
162
+ * and backslash-newline is a line continuation (dropped).
163
+ */
164
+ tokens: string[];
165
+ /** The raw text of the segment, for newline and substring checks. */
166
+ raw: string;
167
+ }
168
+ /**
169
+ * A minimal POSIX-shell tokenizer: splits a command into segments at control
170
+ * operators (`&&`, `||`, `|`, `;`, a background `&`, newline) and each segment
171
+ * into words with quotes resolved. Good enough to find an option's value and a
172
+ * program name; it does not expand anything. Command substitutions `$( … )`
173
+ * and process substitutions `<( … )` / `>( … )` stay inside the word that
174
+ * carries them; grouping `(` and `)` are operators that delimit words. A `#`
175
+ * that begins a word discards the rest of its line, as bash does — comment
176
+ * text is never an argument. With `powershell` set the same walk reads
177
+ * PowerShell's grammar where it differs (see `ScanOptions`).
178
+ */
179
+ export declare function tokenizeShell(command: string, opts?: ScanOptions): ShellSegment[];
180
+ /**
181
+ * The pattern table, in evaluation order. Deny rows first, warn rows after.
182
+ * Each `find` reads only the payload.
183
+ */
184
+ export declare const TRANSPORT_PATTERNS: ReadonlyArray<TransportPattern>;
185
+ /**
186
+ * The gate: parse the payload (throws on an invalid one), walk the table, and
187
+ * return the first deny, else the first warn, else allow. Pure over the payload.
188
+ */
189
+ export declare const transportShieldEvaluator: GateEvaluator;
190
+ //# sourceMappingURL=transport-shield.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport-shield.d.ts","sourceRoot":"","sources":["../src/transport-shield.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,iBAAiB,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyEG;AAEH,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AAEzD,sFAAsF;AACtF,eAAO,MAAM,uBAAuB,mCAAmC,CAAC;AAExE,wFAAwF;AACxF,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAE3C,+DAA+D;AAC/D,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,YAAY,CAAC;AAElD,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,kBAAkB,GAC1B,gBAAgB,GAChB,kBAAkB,GAClB,iBAAiB,GACjB,cAAc,GACd,oBAAoB,GACpB,wBAAwB,CAAC;AAE7B,MAAM,WAAW,cAAc;IAC7B,wGAAwG;IACxG,QAAQ,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,kBAAkB,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,OAAO,EAAE,sBAAsB,GAAG,cAAc,GAAG,IAAI,CAAC;CAC9D;AAID;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,sBAAsB,CA6BpF;AAID,MAAM,WAAW,WAAW;IAC1B,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,MAAM,EAAE,OAAO,CAAC;IAChB,gGAAgG;IAChG,SAAS,EAAE,OAAO,CAAC;IACnB,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAC;IACb,wFAAwF;IACxF,YAAY,EAAE,OAAO,CAAC;IACtB,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAKD;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAkDD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,WAAW,EAAE,CA8JnF;AAwDD,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,qEAAqE;IACrE,GAAG,EAAE,MAAM,CAAC;CACb;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,YAAY,EAAE,CAwIrF;AA8QD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,aAAa,CAAC,gBAAgB,CAuK7D,CAAC;AAeH;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,aAsCtC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transport-shield.fold.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport-shield.fold.test.d.ts","sourceRoot":"","sources":["../src/transport-shield.fold.test.ts"],"names":[],"mappings":""}